msi: Avoid a crash when the cabinet file must be downloaded.
[wine/multimedia.git] / dlls / msi / install.c
blobfa3e4f9e382e7d6cb794962116ae3ac1455aa1b8
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 "wine/debug.h"
31 #include "msi.h"
32 #include "msidefs.h"
33 #include "objbase.h"
34 #include "oleauto.h"
36 #include "msipriv.h"
37 #include "msiserver.h"
38 #include "wine/unicode.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
42 /***********************************************************************
43 * MsiDoActionA (MSI.@)
45 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
47 LPWSTR szwAction;
48 UINT ret;
50 TRACE("%s\n", debugstr_a(szAction));
52 szwAction = strdupAtoW(szAction);
53 if (szAction && !szwAction)
54 return ERROR_FUNCTION_FAILED;
56 ret = MsiDoActionW( hInstall, szwAction );
57 msi_free( szwAction );
58 return ret;
61 /***********************************************************************
62 * MsiDoActionW (MSI.@)
64 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
66 MSIPACKAGE *package;
67 UINT ret;
69 TRACE("%s\n",debugstr_w(szAction));
71 if (!szAction)
72 return ERROR_INVALID_PARAMETER;
74 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
75 if (!package)
77 HRESULT hr;
78 BSTR action;
79 IWineMsiRemotePackage *remote_package;
81 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
82 if (!remote_package)
83 return ERROR_INVALID_HANDLE;
85 action = SysAllocString( szAction );
86 if (!action)
88 IWineMsiRemotePackage_Release( remote_package );
89 return ERROR_OUTOFMEMORY;
92 hr = IWineMsiRemotePackage_DoAction( remote_package, action );
94 SysFreeString( action );
95 IWineMsiRemotePackage_Release( remote_package );
97 if (FAILED(hr))
99 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
100 return HRESULT_CODE(hr);
102 return ERROR_FUNCTION_FAILED;
105 return ERROR_SUCCESS;
108 ret = ACTION_PerformUIAction( package, szAction, -1 );
109 msiobj_release( &package->hdr );
111 return ret;
114 /***********************************************************************
115 * MsiSequenceA (MSI.@)
117 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
119 LPWSTR szwTable;
120 UINT ret;
122 TRACE("%s\n", debugstr_a(szTable));
124 szwTable = strdupAtoW(szTable);
125 if (szTable && !szwTable)
126 return ERROR_FUNCTION_FAILED;
128 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
129 msi_free( szwTable );
130 return ret;
133 /***********************************************************************
134 * MsiSequenceW (MSI.@)
136 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
138 MSIPACKAGE *package;
139 UINT ret;
141 TRACE("%s\n", debugstr_w(szTable));
143 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
144 if (!package)
146 HRESULT hr;
147 BSTR table;
148 IWineMsiRemotePackage *remote_package;
150 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
151 if (!remote_package)
152 return ERROR_INVALID_HANDLE;
154 table = SysAllocString( szTable );
155 if (!table)
157 IWineMsiRemotePackage_Release( remote_package );
158 return ERROR_OUTOFMEMORY;
161 hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode );
163 SysFreeString( table );
164 IWineMsiRemotePackage_Release( remote_package );
166 if (FAILED(hr))
168 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
169 return HRESULT_CODE(hr);
171 return ERROR_FUNCTION_FAILED;
174 return ERROR_SUCCESS;
177 ret = MSI_Sequence( package, szTable, iSequenceMode );
178 msiobj_release( &package->hdr );
180 return ret;
183 UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
185 UINT len, r = ERROR_SUCCESS;
187 if (awbuf->str.w && !sz )
188 return ERROR_INVALID_PARAMETER;
190 if (!sz)
191 return r;
193 if (awbuf->unicode)
195 len = lstrlenW( str );
196 if (awbuf->str.w)
197 lstrcpynW( awbuf->str.w, str, *sz );
199 else
201 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
202 if (len)
203 len--;
204 WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
205 if ( awbuf->str.a && *sz && (len >= *sz) )
206 awbuf->str.a[*sz - 1] = 0;
209 if (awbuf->str.w && len >= *sz)
210 r = ERROR_MORE_DATA;
211 *sz = len;
212 return r;
215 /***********************************************************************
216 * MsiGetTargetPath (internal)
218 static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
219 awstring *szPathBuf, LPDWORD pcchPathBuf )
221 MSIPACKAGE *package;
222 LPWSTR path;
223 UINT r = ERROR_FUNCTION_FAILED;
225 if (!szFolder)
226 return ERROR_INVALID_PARAMETER;
228 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
229 if (!package)
231 HRESULT hr;
232 IWineMsiRemotePackage *remote_package;
233 LPWSTR value = NULL;
234 BSTR folder;
235 DWORD len;
237 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
238 if (!remote_package)
239 return ERROR_INVALID_HANDLE;
241 folder = SysAllocString( szFolder );
242 if (!folder)
244 IWineMsiRemotePackage_Release( remote_package );
245 return ERROR_OUTOFMEMORY;
248 len = 0;
249 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
250 NULL, &len );
251 if (FAILED(hr))
252 goto done;
254 len++;
255 value = msi_alloc(len * sizeof(WCHAR));
256 if (!value)
258 r = ERROR_OUTOFMEMORY;
259 goto done;
262 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
263 (BSTR *)value, &len);
264 if (FAILED(hr))
265 goto done;
267 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
269 done:
270 IWineMsiRemotePackage_Release( remote_package );
271 SysFreeString( folder );
272 msi_free( value );
274 if (FAILED(hr))
276 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
277 return HRESULT_CODE(hr);
279 return ERROR_FUNCTION_FAILED;
282 return r;
285 path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL );
286 msiobj_release( &package->hdr );
288 if (!path)
289 return ERROR_DIRECTORY;
291 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
292 msi_free( path );
293 return r;
296 /***********************************************************************
297 * MsiGetTargetPathA (MSI.@)
299 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
300 LPSTR szPathBuf, LPDWORD pcchPathBuf )
302 LPWSTR szwFolder;
303 awstring path;
304 UINT r;
306 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
308 szwFolder = strdupAtoW(szFolder);
309 if (szFolder && !szwFolder)
310 return ERROR_FUNCTION_FAILED;
312 path.unicode = FALSE;
313 path.str.a = szPathBuf;
315 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
317 msi_free( szwFolder );
319 return r;
322 /***********************************************************************
323 * MsiGetTargetPathW (MSI.@)
325 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
326 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
328 awstring path;
330 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
332 path.unicode = TRUE;
333 path.str.w = szPathBuf;
335 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
338 /***********************************************************************
339 * MsiGetSourcePath (internal)
341 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
342 awstring *szPathBuf, LPDWORD pcchPathBuf )
344 MSIPACKAGE *package;
345 LPWSTR path;
346 UINT r = ERROR_FUNCTION_FAILED;
348 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
350 if (!szFolder)
351 return ERROR_INVALID_PARAMETER;
353 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
354 if (!package)
356 HRESULT hr;
357 IWineMsiRemotePackage *remote_package;
358 LPWSTR value = NULL;
359 BSTR folder;
360 DWORD len;
362 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
363 if (!remote_package)
364 return ERROR_INVALID_HANDLE;
366 folder = SysAllocString( szFolder );
367 if (!folder)
369 IWineMsiRemotePackage_Release( remote_package );
370 return ERROR_OUTOFMEMORY;
373 len = 0;
374 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
375 NULL, &len );
376 if (FAILED(hr))
377 goto done;
379 len++;
380 value = msi_alloc(len * sizeof(WCHAR));
381 if (!value)
383 r = ERROR_OUTOFMEMORY;
384 goto done;
387 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
388 (BSTR *)value, &len);
389 if (FAILED(hr))
390 goto done;
392 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
394 done:
395 IWineMsiRemotePackage_Release( remote_package );
396 SysFreeString( folder );
397 msi_free( value );
399 if (FAILED(hr))
401 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
402 return HRESULT_CODE(hr);
404 return ERROR_FUNCTION_FAILED;
407 return r;
410 if (szPathBuf->str.w && !pcchPathBuf )
412 msiobj_release( &package->hdr );
413 return ERROR_INVALID_PARAMETER;
416 path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL);
417 msiobj_release( &package->hdr );
419 TRACE("path = %s\n",debugstr_w(path));
420 if (!path)
421 return ERROR_DIRECTORY;
423 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
424 msi_free( path );
425 return r;
428 /***********************************************************************
429 * MsiGetSourcePathA (MSI.@)
431 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
432 LPSTR szPathBuf, LPDWORD pcchPathBuf )
434 LPWSTR folder;
435 awstring str;
436 UINT r;
438 TRACE("%s %p %p\n", szFolder, debugstr_a(szPathBuf), pcchPathBuf);
440 str.unicode = FALSE;
441 str.str.a = szPathBuf;
443 folder = strdupAtoW( szFolder );
444 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
445 msi_free( folder );
447 return r;
450 /***********************************************************************
451 * MsiGetSourcePathW (MSI.@)
453 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
454 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
456 awstring str;
458 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
460 str.unicode = TRUE;
461 str.str.w = szPathBuf;
463 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
466 /***********************************************************************
467 * MsiSetTargetPathA (MSI.@)
469 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
470 LPCSTR szFolderPath )
472 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
473 UINT rc = ERROR_OUTOFMEMORY;
475 if ( !szFolder || !szFolderPath )
476 return ERROR_INVALID_PARAMETER;
478 szwFolder = strdupAtoW(szFolder);
479 szwFolderPath = strdupAtoW(szFolderPath);
480 if (!szwFolder || !szwFolderPath)
481 goto end;
483 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
485 end:
486 msi_free(szwFolder);
487 msi_free(szwFolderPath);
489 return rc;
493 * Ok my original interpretation of this was wrong. And it looks like msdn has
494 * changed a bit also. The given folder path does not have to actually already
495 * exist, it just cannot be read only and must be a legal folder path.
497 UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
498 LPCWSTR szFolderPath)
500 DWORD attrib;
501 LPWSTR path = NULL;
502 LPWSTR path2 = NULL;
503 MSIFOLDER *folder;
504 MSIFILE *file;
506 TRACE("%p %s %s\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
508 attrib = GetFileAttributesW(szFolderPath);
509 /* native MSI tests writeability by making temporary files at each drive */
510 if ( attrib != INVALID_FILE_ATTRIBUTES &&
511 (attrib & FILE_ATTRIBUTE_OFFLINE ||
512 attrib & FILE_ATTRIBUTE_READONLY))
513 return ERROR_FUNCTION_FAILED;
515 path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder);
516 if (!path)
517 return ERROR_DIRECTORY;
519 msi_free(folder->Property);
520 folder->Property = build_directory_name(2, szFolderPath, NULL);
522 if (lstrcmpiW(path, folder->Property) == 0)
525 * Resolved Target has not really changed, so just
526 * set this folder and do not recalculate everything.
528 msi_free(folder->ResolvedTarget);
529 folder->ResolvedTarget = NULL;
530 path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL);
531 msi_free(path2);
533 else
535 MSIFOLDER *f;
537 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
539 msi_free(f->ResolvedTarget);
540 f->ResolvedTarget=NULL;
543 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
545 path2 = resolve_folder(package, f->Directory, FALSE, TRUE, FALSE, NULL);
546 msi_free(path2);
549 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
551 MSICOMPONENT *comp = file->Component;
552 LPWSTR p;
554 if (!comp)
555 continue;
557 p = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL);
558 msi_free(file->TargetPath);
560 file->TargetPath = build_directory_name(2, p, file->FileName);
561 msi_free(p);
564 msi_free(path);
566 return ERROR_SUCCESS;
569 /***********************************************************************
570 * MsiSetTargetPathW (MSI.@)
572 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
573 LPCWSTR szFolderPath)
575 MSIPACKAGE *package;
576 UINT ret;
578 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
580 if ( !szFolder || !szFolderPath )
581 return ERROR_INVALID_PARAMETER;
583 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
584 if (!package)
586 HRESULT hr;
587 BSTR folder, path;
588 IWineMsiRemotePackage *remote_package;
590 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
591 if (!remote_package)
592 return ERROR_INVALID_HANDLE;
594 folder = SysAllocString( szFolder );
595 path = SysAllocString( szFolderPath );
596 if (!folder || !path)
598 SysFreeString(folder);
599 SysFreeString(path);
600 IWineMsiRemotePackage_Release( remote_package );
601 return ERROR_OUTOFMEMORY;
604 hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path );
606 SysFreeString(folder);
607 SysFreeString(path);
608 IWineMsiRemotePackage_Release( remote_package );
610 if (FAILED(hr))
612 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
613 return HRESULT_CODE(hr);
615 return ERROR_FUNCTION_FAILED;
618 return ERROR_SUCCESS;
621 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
622 msiobj_release( &package->hdr );
623 return ret;
626 /***********************************************************************
627 * MsiGetMode (MSI.@)
629 * Returns an internal installer state (if it is running in a mode iRunMode)
631 * PARAMS
632 * hInstall [I] Handle to the installation
633 * hRunMode [I] Checking run mode
634 * MSIRUNMODE_ADMIN Administrative mode
635 * MSIRUNMODE_ADVERTISE Advertisement mode
636 * MSIRUNMODE_MAINTENANCE Maintenance mode
637 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
638 * MSIRUNMODE_LOGENABLED Log file is writing
639 * MSIRUNMODE_OPERATIONS Operations in progress??
640 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
641 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
642 * MSIRUNMODE_CABINET Files from cabinet are installed
643 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
644 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
645 * MSIRUNMODE_RESERVED11 Reserved
646 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
647 * MSIRUNMODE_ZAWENABLED Demand installation is supported
648 * MSIRUNMODE_RESERVED14 Reserved
649 * MSIRUNMODE_RESERVED15 Reserved
650 * MSIRUNMODE_SCHEDULED called from install script
651 * MSIRUNMODE_ROLLBACK called from rollback script
652 * MSIRUNMODE_COMMIT called from commit script
654 * RETURNS
655 * In the state: TRUE
656 * Not in the state: FALSE
659 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
661 MSIPACKAGE *package;
662 BOOL r = FALSE;
664 TRACE("%d %d\n", hInstall, iRunMode);
666 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
667 if (!package)
669 BOOL ret;
670 HRESULT hr;
671 IWineMsiRemotePackage *remote_package;
673 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
674 if (!remote_package)
675 return FALSE;
677 hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret);
678 IWineMsiRemotePackage_Release(remote_package);
680 if (hr == S_OK)
681 return ret;
683 return FALSE;
686 switch (iRunMode)
688 case MSIRUNMODE_WINDOWS9X:
689 if (GetVersion() & 0x80000000)
690 r = TRUE;
691 break;
693 case MSIRUNMODE_OPERATIONS:
694 case MSIRUNMODE_RESERVED11:
695 case MSIRUNMODE_RESERVED14:
696 case MSIRUNMODE_RESERVED15:
697 break;
699 case MSIRUNMODE_SCHEDULED:
700 r = package->scheduled_action_running;
701 break;
703 case MSIRUNMODE_ROLLBACK:
704 r = package->rollback_action_running;
705 break;
707 case MSIRUNMODE_COMMIT:
708 r = package->commit_action_running;
709 break;
711 case MSIRUNMODE_MAINTENANCE:
712 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
713 break;
715 case MSIRUNMODE_REBOOTATEND:
716 r = package->need_reboot;
717 break;
719 default:
720 FIXME("unimplemented run mode: %d\n", iRunMode);
721 r = TRUE;
724 msiobj_release( &package->hdr );
725 return r;
728 /***********************************************************************
729 * MsiSetMode (MSI.@)
731 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
733 MSIPACKAGE *package;
734 UINT r;
736 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
738 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
739 if (!package)
741 HRESULT hr;
742 IWineMsiRemotePackage *remote_package;
744 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
745 if (!remote_package)
746 return FALSE;
748 hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState );
749 IWineMsiRemotePackage_Release( remote_package );
751 if (FAILED(hr))
753 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
754 return HRESULT_CODE(hr);
756 return ERROR_FUNCTION_FAILED;
759 return ERROR_SUCCESS;
762 switch (iRunMode)
764 case MSIRUNMODE_REBOOTATEND:
765 package->need_reboot = 1;
766 r = ERROR_SUCCESS;
767 break;
769 case MSIRUNMODE_REBOOTNOW:
770 FIXME("unimplemented run mode: %d\n", iRunMode);
771 r = ERROR_FUNCTION_FAILED;
772 break;
774 default:
775 r = ERROR_ACCESS_DENIED;
778 msiobj_release( &package->hdr );
779 return r;
782 /***********************************************************************
783 * MsiSetFeatureStateA (MSI.@)
785 * According to the docs, when this is called it immediately recalculates
786 * all the component states as well
788 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
789 INSTALLSTATE iState)
791 LPWSTR szwFeature = NULL;
792 UINT rc;
794 szwFeature = strdupAtoW(szFeature);
796 if (!szwFeature)
797 return ERROR_FUNCTION_FAILED;
799 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
801 msi_free(szwFeature);
803 return rc;
808 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
809 INSTALLSTATE iState)
811 UINT rc = ERROR_SUCCESS;
812 MSIFEATURE *feature, *child;
814 TRACE("%s %i\n", debugstr_w(szFeature), iState);
816 feature = get_loaded_feature(package,szFeature);
817 if (!feature)
818 return ERROR_UNKNOWN_FEATURE;
820 if (iState == INSTALLSTATE_ADVERTISED &&
821 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
822 return ERROR_FUNCTION_FAILED;
824 msi_feature_set_state(package, feature, iState);
826 ACTION_UpdateComponentStates(package,szFeature);
828 /* update all the features that are children of this feature */
829 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
831 if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
832 MSI_SetFeatureStateW(package, child->Feature, iState);
835 return rc;
838 /***********************************************************************
839 * MsiSetFeatureStateW (MSI.@)
841 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
842 INSTALLSTATE iState)
844 MSIPACKAGE* package;
845 UINT rc = ERROR_SUCCESS;
847 TRACE("%s %i\n",debugstr_w(szFeature), iState);
849 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
850 if (!package)
852 HRESULT hr;
853 BSTR feature;
854 IWineMsiRemotePackage *remote_package;
856 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
857 if (!remote_package)
858 return ERROR_INVALID_HANDLE;
860 feature = SysAllocString(szFeature);
861 if (!feature)
863 IWineMsiRemotePackage_Release(remote_package);
864 return ERROR_OUTOFMEMORY;
867 hr = IWineMsiRemotePackage_SetFeatureState(remote_package, feature, iState);
869 SysFreeString(feature);
870 IWineMsiRemotePackage_Release(remote_package);
872 if (FAILED(hr))
874 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
875 return HRESULT_CODE(hr);
877 return ERROR_FUNCTION_FAILED;
880 return ERROR_SUCCESS;
883 rc = MSI_SetFeatureStateW(package,szFeature,iState);
885 msiobj_release( &package->hdr );
886 return rc;
889 /***********************************************************************
890 * MsiGetFeatureStateA (MSI.@)
892 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
893 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
895 LPWSTR szwFeature = NULL;
896 UINT rc;
898 szwFeature = strdupAtoW(szFeature);
900 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
902 msi_free( szwFeature);
904 return rc;
907 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
908 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
910 MSIFEATURE *feature;
912 feature = get_loaded_feature(package,szFeature);
913 if (!feature)
914 return ERROR_UNKNOWN_FEATURE;
916 if (piInstalled)
917 *piInstalled = feature->Installed;
919 if (piAction)
920 *piAction = feature->Action;
922 TRACE("returning %i %i\n", feature->Installed, feature->Action);
924 return ERROR_SUCCESS;
927 /***********************************************************************
928 * MsiGetFeatureStateW (MSI.@)
930 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
931 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
933 MSIPACKAGE* package;
934 UINT ret;
936 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
938 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
939 if (!package)
941 HRESULT hr;
942 BSTR feature;
943 IWineMsiRemotePackage *remote_package;
945 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
946 if (!remote_package)
947 return ERROR_INVALID_HANDLE;
949 feature = SysAllocString(szFeature);
950 if (!feature)
952 IWineMsiRemotePackage_Release(remote_package);
953 return ERROR_OUTOFMEMORY;
956 hr = IWineMsiRemotePackage_GetFeatureState(remote_package, feature,
957 piInstalled, piAction);
959 SysFreeString(feature);
960 IWineMsiRemotePackage_Release(remote_package);
962 if (FAILED(hr))
964 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
965 return HRESULT_CODE(hr);
967 return ERROR_FUNCTION_FAILED;
970 return ERROR_SUCCESS;
973 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
974 msiobj_release( &package->hdr );
975 return ret;
978 /***********************************************************************
979 * MsiGetFeatureCostA (MSI.@)
981 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
982 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
984 LPWSTR szwFeature = NULL;
985 UINT rc;
987 szwFeature = strdupAtoW(szFeature);
989 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
991 msi_free(szwFeature);
993 return rc;
996 static INT feature_cost( MSIFEATURE *feature )
998 INT cost = 0;
999 MSICOMPONENT *comp;
1001 LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry )
1003 cost += comp->Cost;
1005 return cost;
1008 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1009 INSTALLSTATE state, LPINT cost )
1011 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1013 *cost = 0;
1014 switch (tree)
1016 case MSICOSTTREE_CHILDREN:
1018 MSIFEATURE *child;
1020 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1022 if (child->ActionRequest == state)
1023 *cost += feature_cost( child );
1025 break;
1027 case MSICOSTTREE_PARENTS:
1029 const WCHAR *feature_parent = feature->Feature_Parent;
1030 for (;;)
1032 MSIFEATURE *parent = get_loaded_feature( package, feature_parent );
1033 if (!parent)
1034 break;
1036 if (parent->ActionRequest == state)
1037 *cost += feature_cost( parent );
1039 feature_parent = parent->Feature_Parent;
1041 break;
1043 case MSICOSTTREE_SELFONLY:
1044 if (feature->ActionRequest == state)
1045 *cost = feature_cost( feature );
1046 break;
1048 default:
1049 WARN("unhandled cost tree %u\n", tree);
1050 break;
1053 *cost /= 512;
1054 return ERROR_SUCCESS;
1057 /***********************************************************************
1058 * MsiGetFeatureCostW (MSI.@)
1060 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1061 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1063 MSIPACKAGE *package;
1064 MSIFEATURE *feature;
1065 UINT ret;
1067 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1068 iCostTree, iState, piCost);
1070 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1071 if (!package)
1073 HRESULT hr;
1074 BSTR feature;
1075 IWineMsiRemotePackage *remote_package;
1077 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1078 if (!remote_package)
1079 return ERROR_INVALID_HANDLE;
1081 feature = SysAllocString(szFeature);
1082 if (!feature)
1084 IWineMsiRemotePackage_Release(remote_package);
1085 return ERROR_OUTOFMEMORY;
1088 hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
1089 iCostTree, iState, piCost);
1091 SysFreeString(feature);
1092 IWineMsiRemotePackage_Release(remote_package);
1094 if (FAILED(hr))
1096 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1097 return HRESULT_CODE(hr);
1099 return ERROR_FUNCTION_FAILED;
1102 return ERROR_SUCCESS;
1105 feature = get_loaded_feature(package, szFeature);
1107 if (feature)
1108 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1109 else
1110 ret = ERROR_UNKNOWN_FEATURE;
1112 msiobj_release( &package->hdr );
1113 return ret;
1116 /***********************************************************************
1117 * MsiSetComponentStateA (MSI.@)
1119 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1120 INSTALLSTATE iState)
1122 UINT rc;
1123 LPWSTR szwComponent = strdupAtoW(szComponent);
1125 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1127 msi_free(szwComponent);
1129 return rc;
1132 /***********************************************************************
1133 * MsiGetComponentStateA (MSI.@)
1135 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1136 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1138 LPWSTR szwComponent= NULL;
1139 UINT rc;
1141 szwComponent= strdupAtoW(szComponent);
1143 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1145 msi_free( szwComponent);
1147 return rc;
1150 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1151 INSTALLSTATE iState)
1153 MSICOMPONENT *comp;
1155 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1157 comp = get_loaded_component(package, szComponent);
1158 if (!comp)
1159 return ERROR_UNKNOWN_COMPONENT;
1161 comp->Installed = iState;
1163 return ERROR_SUCCESS;
1166 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1167 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1169 MSICOMPONENT *comp;
1171 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1172 piInstalled, piAction);
1174 comp = get_loaded_component(package,szComponent);
1175 if (!comp)
1176 return ERROR_UNKNOWN_COMPONENT;
1178 if (piInstalled)
1179 *piInstalled = comp->Installed;
1181 if (piAction)
1182 *piAction = comp->Action;
1184 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1186 return ERROR_SUCCESS;
1189 /***********************************************************************
1190 * MsiSetComponentStateW (MSI.@)
1192 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1193 INSTALLSTATE iState)
1195 MSIPACKAGE* package;
1196 UINT ret;
1198 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1199 if (!package)
1201 HRESULT hr;
1202 BSTR component;
1203 IWineMsiRemotePackage *remote_package;
1205 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1206 if (!remote_package)
1207 return ERROR_INVALID_HANDLE;
1209 component = SysAllocString(szComponent);
1210 if (!component)
1212 IWineMsiRemotePackage_Release(remote_package);
1213 return ERROR_OUTOFMEMORY;
1216 hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState);
1218 SysFreeString(component);
1219 IWineMsiRemotePackage_Release(remote_package);
1221 if (FAILED(hr))
1223 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1224 return HRESULT_CODE(hr);
1226 return ERROR_FUNCTION_FAILED;
1229 return ERROR_SUCCESS;
1232 ret = MSI_SetComponentStateW(package, szComponent, iState);
1233 msiobj_release(&package->hdr);
1234 return ret;
1237 /***********************************************************************
1238 * MsiGetComponentStateW (MSI.@)
1240 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1241 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1243 MSIPACKAGE* package;
1244 UINT ret;
1246 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1247 piInstalled, piAction);
1249 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1250 if (!package)
1252 HRESULT hr;
1253 BSTR component;
1254 IWineMsiRemotePackage *remote_package;
1256 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1257 if (!remote_package)
1258 return ERROR_INVALID_HANDLE;
1260 component = SysAllocString(szComponent);
1261 if (!component)
1263 IWineMsiRemotePackage_Release(remote_package);
1264 return ERROR_OUTOFMEMORY;
1267 hr = IWineMsiRemotePackage_GetComponentState(remote_package, component,
1268 piInstalled, piAction);
1270 SysFreeString(component);
1271 IWineMsiRemotePackage_Release(remote_package);
1273 if (FAILED(hr))
1275 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1276 return HRESULT_CODE(hr);
1278 return ERROR_FUNCTION_FAILED;
1281 return ERROR_SUCCESS;
1284 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1285 msiobj_release( &package->hdr );
1286 return ret;
1289 /***********************************************************************
1290 * MsiGetLanguage (MSI.@)
1292 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1294 MSIPACKAGE* package;
1295 LANGID langid;
1296 static const WCHAR szProductLanguage[] =
1297 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
1299 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1300 if (!package)
1302 HRESULT hr;
1303 LANGID lang;
1304 IWineMsiRemotePackage *remote_package;
1306 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1307 if (!remote_package)
1308 return ERROR_INVALID_HANDLE;
1310 hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang);
1312 if (SUCCEEDED(hr))
1313 return lang;
1315 return 0;
1318 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1319 msiobj_release( &package->hdr );
1320 return langid;
1323 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1325 static const WCHAR szInstallLevel[] = {
1326 'I','N','S','T','A','L','L','L','E','V','E','L',0 };
1327 static const WCHAR fmt[] = { '%','d',0 };
1328 WCHAR level[6];
1329 UINT r;
1331 TRACE("%p %i\n", package, iInstallLevel);
1333 if (iInstallLevel > 32767)
1334 return ERROR_INVALID_PARAMETER;
1336 if (iInstallLevel < 1)
1337 return MSI_SetFeatureStates( package );
1339 sprintfW( level, fmt, iInstallLevel );
1340 r = msi_set_property( package->db, szInstallLevel, level );
1341 if ( r == ERROR_SUCCESS )
1342 r = MSI_SetFeatureStates( package );
1344 return r;
1347 /***********************************************************************
1348 * MsiSetInstallLevel (MSI.@)
1350 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1352 MSIPACKAGE* package;
1353 UINT r;
1355 TRACE("%d %i\n", hInstall, iInstallLevel);
1357 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1358 if (!package)
1360 HRESULT hr;
1361 IWineMsiRemotePackage *remote_package;
1363 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1364 if (!remote_package)
1365 return ERROR_INVALID_HANDLE;
1367 hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel);
1369 IWineMsiRemotePackage_Release(remote_package);
1371 if (FAILED(hr))
1373 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1374 return HRESULT_CODE(hr);
1376 return ERROR_FUNCTION_FAILED;
1379 return ERROR_SUCCESS;
1382 r = MSI_SetInstallLevel( package, iInstallLevel );
1384 msiobj_release( &package->hdr );
1386 return r;
1389 /***********************************************************************
1390 * MsiGetFeatureValidStatesW (MSI.@)
1392 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1393 LPDWORD pInstallState)
1395 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1396 FIXME("%d %s %p stub returning %d\n",
1397 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1399 return ERROR_SUCCESS;
1402 /***********************************************************************
1403 * MsiGetFeatureValidStatesA (MSI.@)
1405 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1406 LPDWORD pInstallState)
1408 UINT ret;
1409 LPWSTR szwFeature = strdupAtoW(szFeature);
1411 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1413 msi_free(szwFeature);
1415 return ret;