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"
36 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
38 /***********************************************************************
39 * MsiDoActionA (MSI.@)
41 UINT WINAPI
MsiDoActionA( MSIHANDLE hInstall
, LPCSTR szAction
)
46 TRACE("%s\n", debugstr_a(szAction
));
48 szwAction
= strdupAtoW(szAction
);
49 if (szAction
&& !szwAction
)
50 return ERROR_FUNCTION_FAILED
;
52 ret
= MsiDoActionW( hInstall
, szwAction
);
53 msi_free( szwAction
);
57 /***********************************************************************
58 * MsiDoActionW (MSI.@)
60 UINT WINAPI
MsiDoActionW( MSIHANDLE hInstall
, LPCWSTR szAction
)
65 TRACE("%s\n",debugstr_w(szAction
));
68 return ERROR_INVALID_PARAMETER
;
70 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
72 return ERROR_INVALID_HANDLE
;
74 ret
= ACTION_PerformUIAction( package
, szAction
);
75 msiobj_release( &package
->hdr
);
80 /***********************************************************************
81 * MsiSequenceA (MSI.@)
83 UINT WINAPI
MsiSequenceA( MSIHANDLE hInstall
, LPCSTR szTable
, INT iSequenceMode
)
88 TRACE("%s\n", debugstr_a(szTable
));
90 szwTable
= strdupAtoW(szTable
);
91 if (szTable
&& !szwTable
)
92 return ERROR_FUNCTION_FAILED
;
94 ret
= MsiSequenceW( hInstall
, szwTable
, iSequenceMode
);
99 /***********************************************************************
100 * MsiSequenceW (MSI.@)
102 UINT WINAPI
MsiSequenceW( MSIHANDLE hInstall
, LPCWSTR szTable
, INT iSequenceMode
)
107 TRACE("%s\n", debugstr_w(szTable
));
109 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
111 return ERROR_INVALID_HANDLE
;
113 ret
= MSI_Sequence( package
, szTable
, iSequenceMode
);
114 msiobj_release( &package
->hdr
);
119 UINT
msi_strcpy_to_awstring( LPCWSTR str
, awstring
*awbuf
, DWORD
*sz
)
121 UINT len
, r
= ERROR_SUCCESS
;
123 if (awbuf
->str
.w
&& !sz
)
124 return ERROR_INVALID_PARAMETER
;
131 len
= lstrlenW( str
);
133 lstrcpynW( awbuf
->str
.w
, str
, *sz
);
137 len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
140 WideCharToMultiByte( CP_ACP
, 0, str
, -1, awbuf
->str
.a
, *sz
, NULL
, NULL
);
141 if ( *sz
&& (len
>= *sz
) )
142 awbuf
->str
.a
[*sz
- 1] = 0;
145 if (awbuf
->str
.w
&& len
>= *sz
)
151 /***********************************************************************
152 * MsiGetTargetPath (internal)
154 UINT WINAPI
MSI_GetTargetPath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
155 awstring
*szPathBuf
, DWORD
* pcchPathBuf
)
162 return ERROR_INVALID_PARAMETER
;
164 package
= msihandle2msiinfo( hInstall
, MSIHANDLETYPE_PACKAGE
);
166 return ERROR_INVALID_HANDLE
;
168 path
= resolve_folder( package
, szFolder
, FALSE
, FALSE
, NULL
);
169 msiobj_release( &package
->hdr
);
172 return ERROR_DIRECTORY
;
174 r
= msi_strcpy_to_awstring( path
, szPathBuf
, pcchPathBuf
);
179 /***********************************************************************
180 * MsiGetTargetPathA (MSI.@)
182 UINT WINAPI
MsiGetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
183 LPSTR szPathBuf
, DWORD
* pcchPathBuf
)
189 TRACE("%s %p %p\n", debugstr_a(szFolder
), szPathBuf
, pcchPathBuf
);
191 szwFolder
= strdupAtoW(szFolder
);
192 if (szFolder
&& !szwFolder
)
193 return ERROR_FUNCTION_FAILED
;
195 path
.unicode
= FALSE
;
196 path
.str
.a
= szPathBuf
;
198 r
= MSI_GetTargetPath( hInstall
, szwFolder
, &path
, pcchPathBuf
);
200 msi_free( szwFolder
);
205 /***********************************************************************
206 * MsiGetTargetPathW (MSI.@)
208 UINT WINAPI
MsiGetTargetPathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
209 LPWSTR szPathBuf
, DWORD
* pcchPathBuf
)
213 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
216 path
.str
.w
= szPathBuf
;
218 return MSI_GetTargetPath( hInstall
, szFolder
, &path
, pcchPathBuf
);
221 /***********************************************************************
222 * MsiGetSourcePath (internal)
224 static UINT
MSI_GetSourcePath( MSIHANDLE hInstall
, LPCWSTR szFolder
,
225 awstring
*szPathBuf
, DWORD
* pcchPathBuf
)
231 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
234 return ERROR_INVALID_PARAMETER
;
236 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
238 return ERROR_INVALID_HANDLE
;
240 if (szPathBuf
->str
.w
&& !pcchPathBuf
)
242 msiobj_release( &package
->hdr
);
243 return ERROR_INVALID_PARAMETER
;
246 path
= resolve_folder(package
, szFolder
, TRUE
, FALSE
, NULL
);
247 msiobj_release( &package
->hdr
);
249 TRACE("path = %s\n",debugstr_w(path
));
251 return ERROR_DIRECTORY
;
253 r
= msi_strcpy_to_awstring( path
, szPathBuf
, pcchPathBuf
);
258 /***********************************************************************
259 * MsiGetSourcePathA (MSI.@)
261 UINT WINAPI
MsiGetSourcePathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
262 LPSTR szPathBuf
, DWORD
* pcchPathBuf
)
268 TRACE("%s %p %p\n", szFolder
, debugstr_a(szPathBuf
), pcchPathBuf
);
271 str
.str
.a
= szPathBuf
;
273 folder
= strdupAtoW( szFolder
);
274 r
= MSI_GetSourcePath( hInstall
, folder
, &str
, pcchPathBuf
);
280 /***********************************************************************
281 * MsiGetSourcePathW (MSI.@)
283 UINT WINAPI
MsiGetSourcePathW( MSIHANDLE hInstall
, LPCWSTR szFolder
,
284 LPWSTR szPathBuf
, DWORD
* pcchPathBuf
)
288 TRACE("%s %p %p\n", debugstr_w(szFolder
), szPathBuf
, pcchPathBuf
);
291 str
.str
.w
= szPathBuf
;
293 return MSI_GetSourcePath( hInstall
, szFolder
, &str
, pcchPathBuf
);
296 /***********************************************************************
297 * MsiSetTargetPathA (MSI.@)
299 UINT WINAPI
MsiSetTargetPathA( MSIHANDLE hInstall
, LPCSTR szFolder
,
300 LPCSTR szFolderPath
)
302 LPWSTR szwFolder
= NULL
, szwFolderPath
= NULL
;
303 UINT rc
= ERROR_OUTOFMEMORY
;
305 if ( !szFolder
|| !szFolderPath
)
306 return ERROR_INVALID_PARAMETER
;
308 szwFolder
= strdupAtoW(szFolder
);
309 szwFolderPath
= strdupAtoW(szFolderPath
);
310 if (!szwFolder
|| !szwFolderPath
)
313 rc
= MsiSetTargetPathW( hInstall
, szwFolder
, szwFolderPath
);
317 msi_free(szwFolderPath
);
323 * Ok my original interpretation of this was wrong. And it looks like msdn has
324 * changed a bit also. The given folder path does not have to actually already
325 * exist, it just cannot be read only and must be a legal folder path.
327 UINT
MSI_SetTargetPathW(MSIPACKAGE
*package
, LPCWSTR szFolder
,
328 LPCWSTR szFolderPath
)
335 TRACE("(%p %s %s)\n",package
, debugstr_w(szFolder
),debugstr_w(szFolderPath
));
337 attrib
= GetFileAttributesW(szFolderPath
);
338 if ( attrib
!= INVALID_FILE_ATTRIBUTES
&&
339 (!(attrib
& FILE_ATTRIBUTE_DIRECTORY
) ||
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 if (attrib
== INVALID_FILE_ATTRIBUTES
)
350 if (!CreateDirectoryW(szFolderPath
,NULL
))
353 return ERROR_FUNCTION_FAILED
;
355 RemoveDirectoryW(szFolderPath
);
358 msi_free(folder
->Property
);
359 folder
->Property
= build_directory_name(2, szFolderPath
, NULL
);
361 if (lstrcmpiW(path
, folder
->Property
) == 0)
364 * Resolved Target has not really changed, so just
365 * set this folder and do not recalculate everything.
367 msi_free(folder
->ResolvedTarget
);
368 folder
->ResolvedTarget
= NULL
;
369 path2
= resolve_folder(package
,szFolder
,FALSE
,TRUE
,NULL
);
376 LIST_FOR_EACH_ENTRY( f
, &package
->folders
, MSIFOLDER
, entry
)
378 msi_free(f
->ResolvedTarget
);
379 f
->ResolvedTarget
=NULL
;
382 LIST_FOR_EACH_ENTRY( f
, &package
->folders
, MSIFOLDER
, entry
)
384 path2
= resolve_folder(package
, f
->Directory
, FALSE
, TRUE
, NULL
);
390 return ERROR_SUCCESS
;
393 /***********************************************************************
394 * MsiSetTargetPathW (MSI.@)
396 UINT WINAPI
MsiSetTargetPathW(MSIHANDLE hInstall
, LPCWSTR szFolder
,
397 LPCWSTR szFolderPath
)
402 TRACE("(%s %s)\n",debugstr_w(szFolder
),debugstr_w(szFolderPath
));
404 if ( !szFolder
|| !szFolderPath
)
405 return ERROR_INVALID_PARAMETER
;
407 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
409 return ERROR_INVALID_HANDLE
;
411 ret
= MSI_SetTargetPathW( package
, szFolder
, szFolderPath
);
412 msiobj_release( &package
->hdr
);
416 /***********************************************************************
419 * Returns an internal installer state (if it is running in a mode iRunMode)
422 * hInstall [I] Handle to the installation
423 * hRunMode [I] Checking run mode
424 * MSIRUNMODE_ADMIN Administrative mode
425 * MSIRUNMODE_ADVERTISE Advertisement mode
426 * MSIRUNMODE_MAINTENANCE Maintenance mode
427 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
428 * MSIRUNMODE_LOGENABLED Log file is writing
429 * MSIRUNMODE_OPERATIONS Operations in progress??
430 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
431 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
432 * MSIRUNMODE_CABINET Files from cabinet are installed
433 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
434 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
435 * MSIRUNMODE_RESERVED11 Reserved
436 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
437 * MSIRUNMODE_ZAWENABLED Demand installation is supported
438 * MSIRUNMODE_RESERVED14 Reserved
439 * MSIRUNMODE_RESERVED15 Reserved
440 * MSIRUNMODE_SCHEDULED called from install script
441 * MSIRUNMODE_ROLLBACK called from rollback script
442 * MSIRUNMODE_COMMIT called from commit script
446 * Not in the state: FALSE
450 BOOL WINAPI
MsiGetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
)
456 case MSIRUNMODE_WINDOWS9X
:
457 if (GetVersion() & 0x80000000)
461 case MSIRUNMODE_RESERVED11
:
462 case MSIRUNMODE_RESERVED14
:
463 case MSIRUNMODE_RESERVED15
:
466 case MSIRUNMODE_SCHEDULED
:
467 case MSIRUNMODE_ROLLBACK
:
468 case MSIRUNMODE_COMMIT
:
472 FIXME("%ld %d\n", hInstall
, iRunMode
);
479 /***********************************************************************
482 BOOL WINAPI
MsiSetMode(MSIHANDLE hInstall
, MSIRUNMODE iRunMode
, BOOL fState
)
486 case MSIRUNMODE_RESERVED11
:
487 case MSIRUNMODE_WINDOWS9X
:
488 case MSIRUNMODE_RESERVED14
:
489 case MSIRUNMODE_RESERVED15
:
492 FIXME("%ld %d %d\n", hInstall
, iRunMode
, fState
);
497 /***********************************************************************
498 * MsiSetFeatureStateA (MSI.@)
500 * According to the docs, when this is called it immediately recalculates
501 * all the component states as well
503 UINT WINAPI
MsiSetFeatureStateA(MSIHANDLE hInstall
, LPCSTR szFeature
,
506 LPWSTR szwFeature
= NULL
;
509 szwFeature
= strdupAtoW(szFeature
);
512 return ERROR_FUNCTION_FAILED
;
514 rc
= MsiSetFeatureStateW(hInstall
,szwFeature
, iState
);
516 msi_free(szwFeature
);
523 UINT WINAPI
MSI_SetFeatureStateW(MSIPACKAGE
* package
, LPCWSTR szFeature
,
526 UINT rc
= ERROR_SUCCESS
;
527 MSIFEATURE
*feature
, *child
;
529 TRACE(" %s to %i\n",debugstr_w(szFeature
), iState
);
531 feature
= get_loaded_feature(package
,szFeature
);
533 return ERROR_UNKNOWN_FEATURE
;
535 if (iState
== INSTALLSTATE_ADVERTISED
&&
536 feature
->Attributes
& msidbFeatureAttributesDisallowAdvertise
)
537 return ERROR_FUNCTION_FAILED
;
539 feature
->ActionRequest
= iState
;
540 feature
->Action
= iState
;
542 ACTION_UpdateComponentStates(package
,szFeature
);
544 /* update all the features that are children of this feature */
545 LIST_FOR_EACH_ENTRY( child
, &package
->features
, MSIFEATURE
, entry
)
547 if (lstrcmpW(szFeature
, child
->Feature_Parent
) == 0)
548 MSI_SetFeatureStateW(package
, child
->Feature
, iState
);
554 /***********************************************************************
555 * MsiSetFeatureStateW (MSI.@)
557 UINT WINAPI
MsiSetFeatureStateW(MSIHANDLE hInstall
, LPCWSTR szFeature
,
561 UINT rc
= ERROR_SUCCESS
;
563 TRACE(" %s to %i\n",debugstr_w(szFeature
), iState
);
565 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
567 return ERROR_INVALID_HANDLE
;
569 rc
= MSI_SetFeatureStateW(package
,szFeature
,iState
);
571 msiobj_release( &package
->hdr
);
575 /***********************************************************************
576 * MsiGetFeatureStateA (MSI.@)
578 UINT WINAPI
MsiGetFeatureStateA(MSIHANDLE hInstall
, LPSTR szFeature
,
579 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
581 LPWSTR szwFeature
= NULL
;
584 szwFeature
= strdupAtoW(szFeature
);
586 rc
= MsiGetFeatureStateW(hInstall
,szwFeature
,piInstalled
, piAction
);
588 msi_free( szwFeature
);
593 UINT
MSI_GetFeatureStateW(MSIPACKAGE
*package
, LPWSTR szFeature
,
594 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
598 feature
= get_loaded_feature(package
,szFeature
);
600 return ERROR_UNKNOWN_FEATURE
;
603 *piInstalled
= feature
->Installed
;
606 *piAction
= feature
->Action
;
608 TRACE("returning %i %i\n", feature
->Installed
, feature
->Action
);
610 return ERROR_SUCCESS
;
613 /***********************************************************************
614 * MsiGetFeatureStateW (MSI.@)
616 UINT WINAPI
MsiGetFeatureStateW(MSIHANDLE hInstall
, LPWSTR szFeature
,
617 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
622 TRACE("%ld %s %p %p\n", hInstall
, debugstr_w(szFeature
), piInstalled
,
625 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
627 return ERROR_INVALID_HANDLE
;
628 ret
= MSI_GetFeatureStateW(package
, szFeature
, piInstalled
, piAction
);
629 msiobj_release( &package
->hdr
);
633 /***********************************************************************
634 * MsiSetComponentStateA (MSI.@)
636 UINT WINAPI
MsiSetComponentStateA(MSIHANDLE hInstall
, LPCSTR szComponent
,
640 LPWSTR szwComponent
= strdupAtoW(szComponent
);
642 rc
= MsiSetComponentStateW(hInstall
, szwComponent
, iState
);
644 msi_free(szwComponent
);
649 /***********************************************************************
650 * MsiGetComponentStateA (MSI.@)
652 UINT WINAPI
MsiGetComponentStateA(MSIHANDLE hInstall
, LPSTR szComponent
,
653 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
655 LPWSTR szwComponent
= NULL
;
658 szwComponent
= strdupAtoW(szComponent
);
660 rc
= MsiGetComponentStateW(hInstall
,szwComponent
,piInstalled
, piAction
);
662 msi_free( szwComponent
);
667 static UINT
MSI_SetComponentStateW(MSIPACKAGE
*package
, LPCWSTR szComponent
,
672 TRACE("%p %s %d\n", package
, debugstr_w(szComponent
), iState
);
674 comp
= get_loaded_component(package
, szComponent
);
676 return ERROR_UNKNOWN_COMPONENT
;
678 comp
->Installed
= iState
;
680 return ERROR_SUCCESS
;
683 UINT
MSI_GetComponentStateW(MSIPACKAGE
*package
, LPWSTR szComponent
,
684 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
688 TRACE("%p %s %p %p\n", package
, debugstr_w(szComponent
),
689 piInstalled
, piAction
);
691 comp
= get_loaded_component(package
,szComponent
);
693 return ERROR_UNKNOWN_COMPONENT
;
696 *piInstalled
= comp
->Installed
;
699 *piAction
= comp
->Action
;
701 TRACE("states (%i, %i)\n", comp
->Installed
, comp
->Action
);
703 return ERROR_SUCCESS
;
706 /***********************************************************************
707 * MsiSetComponentStateW (MSI.@)
709 UINT WINAPI
MsiSetComponentStateW(MSIHANDLE hInstall
, LPCWSTR szComponent
,
715 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
717 return ERROR_INVALID_HANDLE
;
718 ret
= MSI_SetComponentStateW(package
, szComponent
, iState
);
719 msiobj_release(&package
->hdr
);
723 /***********************************************************************
724 * MsiGetComponentStateW (MSI.@)
726 UINT WINAPI
MsiGetComponentStateW(MSIHANDLE hInstall
, LPWSTR szComponent
,
727 INSTALLSTATE
*piInstalled
, INSTALLSTATE
*piAction
)
732 TRACE("%ld %s %p %p\n", hInstall
, debugstr_w(szComponent
),
733 piInstalled
, piAction
);
735 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
737 return ERROR_INVALID_HANDLE
;
738 ret
= MSI_GetComponentStateW( package
, szComponent
, piInstalled
, piAction
);
739 msiobj_release( &package
->hdr
);
743 /***********************************************************************
744 * MsiGetLanguage (MSI.@)
746 LANGID WINAPI
MsiGetLanguage(MSIHANDLE hInstall
)
751 static const WCHAR szProductLanguage
[] =
752 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
754 package
= msihandle2msiinfo(hInstall
, MSIHANDLETYPE_PACKAGE
);
756 return ERROR_INVALID_HANDLE
;
758 buffer
= msi_dup_property( package
, szProductLanguage
);
759 langid
= atoiW(buffer
);
762 msiobj_release (&package
->hdr
);