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 */
28 #include "wine/debug.h"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37 /***********************************************************************
38 * MsiDoActionA (MSI.@)
40 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
45 TRACE("%s\n", debugstr_a(szAction));
47 szwAction = strdupAtoW(szAction);
48 if (szAction && !szwAction)
49 return ERROR_FUNCTION_FAILED;
51 ret = MsiDoActionW( hInstall, szwAction );
52 msi_free( szwAction );
56 /***********************************************************************
57 * MsiDoActionW (MSI.@)
59 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
64 TRACE("%s\n",debugstr_w(szAction));
67 return ERROR_INVALID_PARAMETER;
69 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
71 return ERROR_INVALID_HANDLE;
73 ret = ACTION_PerformUIAction( package, szAction );
74 msiobj_release( &package->hdr );
79 /***********************************************************************
80 * MsiSequenceA (MSI.@)
82 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
87 TRACE("%s\n", debugstr_a(szTable));
89 szwTable = strdupAtoW(szTable);
90 if (szTable && !szwTable)
91 return ERROR_FUNCTION_FAILED;
93 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
98 /***********************************************************************
99 * MsiSequenceW (MSI.@)
101 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
106 TRACE("%s\n", debugstr_w(szTable));
108 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
110 return ERROR_INVALID_HANDLE;
112 ret = MSI_Sequence( package, szTable, iSequenceMode );
113 msiobj_release( &package->hdr );
118 UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
120 UINT len, r = ERROR_SUCCESS;
122 if (awbuf->str.w && !sz )
123 return ERROR_INVALID_PARAMETER;
130 len = lstrlenW( str );
132 lstrcpynW( awbuf->str.w, str, *sz );
136 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
139 WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
140 if ( *sz && (len >= *sz) )
141 awbuf->str.a[*sz - 1] = 0;
144 if (awbuf->str.w && len >= *sz)
150 /***********************************************************************
151 * MsiGetTargetPath (internal)
153 UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
154 awstring *szPathBuf, DWORD* pcchPathBuf )
161 return ERROR_INVALID_PARAMETER;
163 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
165 return ERROR_INVALID_HANDLE;
167 path = resolve_folder( package, szFolder, FALSE, FALSE, NULL );
168 msiobj_release( &package->hdr );
171 return ERROR_DIRECTORY;
173 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
178 /***********************************************************************
179 * MsiGetTargetPathA (MSI.@)
181 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
182 LPSTR szPathBuf, DWORD* pcchPathBuf )
188 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
190 szwFolder = strdupAtoW(szFolder);
191 if (szFolder && !szwFolder)
192 return ERROR_FUNCTION_FAILED;
194 path.unicode = FALSE;
195 path.str.a = szPathBuf;
197 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
199 msi_free( szwFolder );
204 /***********************************************************************
205 * MsiGetTargetPathW (MSI.@)
207 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
208 LPWSTR szPathBuf, DWORD* pcchPathBuf )
212 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
215 path.str.w = szPathBuf;
217 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
220 /***********************************************************************
221 * MsiGetSourcePath (internal)
223 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
224 awstring *szPathBuf, DWORD* pcchPathBuf )
230 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
233 return ERROR_INVALID_PARAMETER;
235 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
237 return ERROR_INVALID_HANDLE;
239 if (szPathBuf->str.w && !pcchPathBuf )
241 msiobj_release( &package->hdr );
242 return ERROR_INVALID_PARAMETER;
245 path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
246 msiobj_release( &package->hdr );
248 TRACE("path = %s\n",debugstr_w(path));
250 return ERROR_DIRECTORY;
252 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
257 /***********************************************************************
258 * MsiGetSourcePathA (MSI.@)
260 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
261 LPSTR szPathBuf, DWORD* pcchPathBuf )
267 TRACE("%s %p %p\n", szFolder, debugstr_a(szPathBuf), pcchPathBuf);
270 str.str.a = szPathBuf;
272 folder = strdupAtoW( szFolder );
273 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
279 /***********************************************************************
280 * MsiGetSourcePathW (MSI.@)
282 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
283 LPWSTR szPathBuf, DWORD* pcchPathBuf )
287 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
290 str.str.w = szPathBuf;
292 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
295 /***********************************************************************
296 * MsiSetTargetPathA (MSI.@)
298 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
299 LPCSTR szFolderPath )
301 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
302 UINT rc = ERROR_OUTOFMEMORY;
304 if ( !szFolder || !szFolderPath )
305 return ERROR_INVALID_PARAMETER;
307 szwFolder = strdupAtoW(szFolder);
308 szwFolderPath = strdupAtoW(szFolderPath);
309 if (!szwFolder || !szwFolderPath)
312 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
316 msi_free(szwFolderPath);
322 * Ok my original interpretation of this was wrong. And it looks like msdn has
323 * changed a bit also. The given folder path does not have to actually already
324 * exist, it just cannot be read only and must be a legal folder path.
326 UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
327 LPCWSTR szFolderPath)
335 TRACE("%p %s %s\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
337 attrib = GetFileAttributesW(szFolderPath);
338 /* native MSI tests writeability by making temporary files at each drive */
339 if ( attrib != INVALID_FILE_ATTRIBUTES &&
340 (attrib & FILE_ATTRIBUTE_OFFLINE ||
341 attrib & FILE_ATTRIBUTE_READONLY))
342 return ERROR_FUNCTION_FAILED;
344 path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
346 return ERROR_DIRECTORY;
348 msi_free(folder->Property);
349 folder->Property = build_directory_name(2, szFolderPath, NULL);
351 if (lstrcmpiW(path, folder->Property) == 0)
354 * Resolved Target has not really changed, so just
355 * set this folder and do not recalculate everything.
357 msi_free(folder->ResolvedTarget);
358 folder->ResolvedTarget = NULL;
359 path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
366 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
368 msi_free(f->ResolvedTarget);
369 f->ResolvedTarget=NULL;
372 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
374 path2 = resolve_folder(package, f->Directory, FALSE, TRUE, NULL);
378 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
380 MSICOMPONENT *comp = file->Component;
386 p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
387 msi_free(file->TargetPath);
389 file->TargetPath = build_directory_name(2, p, file->FileName);
395 return ERROR_SUCCESS;
398 /***********************************************************************
399 * MsiSetTargetPathW (MSI.@)
401 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
402 LPCWSTR szFolderPath)
407 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
409 if ( !szFolder || !szFolderPath )
410 return ERROR_INVALID_PARAMETER;
412 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
414 return ERROR_INVALID_HANDLE;
416 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
417 msiobj_release( &package->hdr );
421 /***********************************************************************
424 * Returns an internal installer state (if it is running in a mode iRunMode)
427 * hInstall [I] Handle to the installation
428 * hRunMode [I] Checking run mode
429 * MSIRUNMODE_ADMIN Administrative mode
430 * MSIRUNMODE_ADVERTISE Advertisement mode
431 * MSIRUNMODE_MAINTENANCE Maintenance mode
432 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
433 * MSIRUNMODE_LOGENABLED Log file is writing
434 * MSIRUNMODE_OPERATIONS Operations in progress??
435 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
436 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
437 * MSIRUNMODE_CABINET Files from cabinet are installed
438 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
439 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
440 * MSIRUNMODE_RESERVED11 Reserved
441 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
442 * MSIRUNMODE_ZAWENABLED Demand installation is supported
443 * MSIRUNMODE_RESERVED14 Reserved
444 * MSIRUNMODE_RESERVED15 Reserved
445 * MSIRUNMODE_SCHEDULED called from install script
446 * MSIRUNMODE_ROLLBACK called from rollback script
447 * MSIRUNMODE_COMMIT called from commit script
451 * Not in the state: FALSE
454 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
460 case MSIRUNMODE_WINDOWS9X:
461 if (GetVersion() & 0x80000000)
465 case MSIRUNMODE_RESERVED11:
466 case MSIRUNMODE_RESERVED14:
467 case MSIRUNMODE_RESERVED15:
470 case MSIRUNMODE_SCHEDULED:
471 case MSIRUNMODE_ROLLBACK:
472 case MSIRUNMODE_COMMIT:
476 FIXME("%ld %d\n", hInstall, iRunMode);
483 /***********************************************************************
486 BOOL WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
490 case MSIRUNMODE_RESERVED11:
491 case MSIRUNMODE_WINDOWS9X:
492 case MSIRUNMODE_RESERVED14:
493 case MSIRUNMODE_RESERVED15:
496 FIXME("%ld %d %d\n", hInstall, iRunMode, fState);
501 /***********************************************************************
502 * MsiSetFeatureStateA (MSI.@)
504 * According to the docs, when this is called it immediately recalculates
505 * all the component states as well
507 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
510 LPWSTR szwFeature = NULL;
513 szwFeature = strdupAtoW(szFeature);
516 return ERROR_FUNCTION_FAILED;
518 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
520 msi_free(szwFeature);
527 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
530 UINT rc = ERROR_SUCCESS;
531 MSIFEATURE *feature, *child;
533 TRACE("%s %i\n", debugstr_w(szFeature), iState);
535 feature = get_loaded_feature(package,szFeature);
537 return ERROR_UNKNOWN_FEATURE;
539 if (iState == INSTALLSTATE_ADVERTISED &&
540 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
541 return ERROR_FUNCTION_FAILED;
543 feature->ActionRequest = iState;
544 feature->Action = iState;
546 ACTION_UpdateComponentStates(package,szFeature);
548 /* update all the features that are children of this feature */
549 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
551 if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
552 MSI_SetFeatureStateW(package, child->Feature, iState);
558 /***********************************************************************
559 * MsiSetFeatureStateW (MSI.@)
561 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
565 UINT rc = ERROR_SUCCESS;
567 TRACE("%s %i\n",debugstr_w(szFeature), iState);
569 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
571 return ERROR_INVALID_HANDLE;
573 rc = MSI_SetFeatureStateW(package,szFeature,iState);
575 msiobj_release( &package->hdr );
579 /***********************************************************************
580 * MsiGetFeatureStateA (MSI.@)
582 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
583 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
585 LPWSTR szwFeature = NULL;
588 szwFeature = strdupAtoW(szFeature);
590 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
592 msi_free( szwFeature);
597 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
598 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
602 feature = get_loaded_feature(package,szFeature);
604 return ERROR_UNKNOWN_FEATURE;
607 *piInstalled = feature->Installed;
610 *piAction = feature->Action;
612 TRACE("returning %i %i\n", feature->Installed, feature->Action);
614 return ERROR_SUCCESS;
617 /***********************************************************************
618 * MsiGetFeatureStateW (MSI.@)
620 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
621 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
626 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
628 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
630 return ERROR_INVALID_HANDLE;
631 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
632 msiobj_release( &package->hdr );
636 /***********************************************************************
637 * MsiSetComponentStateA (MSI.@)
639 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
643 LPWSTR szwComponent = strdupAtoW(szComponent);
645 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
647 msi_free(szwComponent);
652 /***********************************************************************
653 * MsiGetComponentStateA (MSI.@)
655 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
656 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
658 LPWSTR szwComponent= NULL;
661 szwComponent= strdupAtoW(szComponent);
663 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
665 msi_free( szwComponent);
670 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
675 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
677 comp = get_loaded_component(package, szComponent);
679 return ERROR_UNKNOWN_COMPONENT;
681 comp->Installed = iState;
683 return ERROR_SUCCESS;
686 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
687 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
691 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
692 piInstalled, piAction);
694 comp = get_loaded_component(package,szComponent);
696 return ERROR_UNKNOWN_COMPONENT;
699 *piInstalled = comp->Installed;
702 *piAction = comp->Action;
704 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
706 return ERROR_SUCCESS;
709 /***********************************************************************
710 * MsiSetComponentStateW (MSI.@)
712 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
718 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
720 return ERROR_INVALID_HANDLE;
721 ret = MSI_SetComponentStateW(package, szComponent, iState);
722 msiobj_release(&package->hdr);
726 /***********************************************************************
727 * MsiGetComponentStateW (MSI.@)
729 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
730 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
735 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
736 piInstalled, piAction);
738 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
740 return ERROR_INVALID_HANDLE;
741 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
742 msiobj_release( &package->hdr );
746 /***********************************************************************
747 * MsiGetLanguage (MSI.@)
749 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
753 static const WCHAR szProductLanguage[] =
754 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
756 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
758 return ERROR_INVALID_HANDLE;
760 langid = msi_get_property_int( package, szProductLanguage, 0 );
761 msiobj_release( &package->hdr );
765 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
767 static const WCHAR szInstallLevel[] = {
768 'I','N','S','T','A','L','L','L','E','V','E','L',0 };
769 static const WCHAR fmt[] = { '%','d',0 };
773 TRACE("%p %i\n", package, iInstallLevel);
775 if (iInstallLevel<1 || iInstallLevel>32767)
776 return ERROR_INVALID_PARAMETER;
778 sprintfW( level, fmt, iInstallLevel );
779 r = MSI_SetPropertyW( package, szInstallLevel, level );
780 if ( r == ERROR_SUCCESS )
782 r = MSI_SetFeatureStates( package );
788 /***********************************************************************
789 * MsiSetInstallLevel (MSI.@)
791 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
796 TRACE("%ld %i\n", hInstall, iInstallLevel);
798 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
800 return ERROR_INVALID_HANDLE;
802 r = MSI_SetInstallLevel( package, iInstallLevel );
804 msiobj_release( &package->hdr );