wininet/tests: Write-strings warnings fix.
[wine/multimedia.git] / dlls / msi / install.c
blob249102fd1e112a291dc81f852fc026b85afaf550
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 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wine/debug.h"
29 #include "msi.h"
30 #include "msidefs.h"
31 #include "msipriv.h"
32 #include "action.h"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37 /***********************************************************************
38 * MsiDoActionA (MSI.@)
40 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
42 LPWSTR szwAction;
43 UINT ret;
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 );
53 return ret;
56 /***********************************************************************
57 * MsiDoActionW (MSI.@)
59 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
61 MSIPACKAGE *package;
62 UINT ret;
64 TRACE("%s\n",debugstr_w(szAction));
66 if (!szAction)
67 return ERROR_INVALID_PARAMETER;
69 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
70 if (!package)
71 return ERROR_INVALID_HANDLE;
73 ret = ACTION_PerformUIAction( package, szAction );
74 msiobj_release( &package->hdr );
76 return ret;
79 /***********************************************************************
80 * MsiSequenceA (MSI.@)
82 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
84 LPWSTR szwTable;
85 UINT ret;
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 );
94 msi_free( szwTable );
95 return ret;
98 /***********************************************************************
99 * MsiSequenceW (MSI.@)
101 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
103 MSIPACKAGE *package;
104 UINT ret;
106 TRACE("%s\n", debugstr_w(szTable));
108 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
109 if (!package)
110 return ERROR_INVALID_HANDLE;
112 ret = MSI_Sequence( package, szTable, iSequenceMode );
113 msiobj_release( &package->hdr );
115 return ret;
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;
125 if (!sz)
126 return r;
128 if (awbuf->unicode)
130 len = lstrlenW( str );
131 if (awbuf->str.w)
132 lstrcpynW( awbuf->str.w, str, *sz );
134 else
136 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
137 if (len)
138 len--;
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)
145 r = ERROR_MORE_DATA;
146 *sz = len;
147 return r;
150 /***********************************************************************
151 * MsiGetTargetPath (internal)
153 UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
154 awstring *szPathBuf, DWORD* pcchPathBuf )
156 MSIPACKAGE *package;
157 LPWSTR path;
158 UINT r;
160 if (!szFolder)
161 return ERROR_INVALID_PARAMETER;
163 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
164 if (!package)
165 return ERROR_INVALID_HANDLE;
167 path = resolve_folder( package, szFolder, FALSE, FALSE, NULL );
168 msiobj_release( &package->hdr );
170 if (!path)
171 return ERROR_DIRECTORY;
173 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
174 msi_free( path );
175 return r;
178 /***********************************************************************
179 * MsiGetTargetPathA (MSI.@)
181 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
182 LPSTR szPathBuf, DWORD* pcchPathBuf )
184 LPWSTR szwFolder;
185 awstring path;
186 UINT r;
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 );
201 return r;
204 /***********************************************************************
205 * MsiGetTargetPathW (MSI.@)
207 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
208 LPWSTR szPathBuf, DWORD* pcchPathBuf )
210 awstring path;
212 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
214 path.unicode = TRUE;
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 )
226 MSIPACKAGE *package;
227 LPWSTR path;
228 UINT r;
230 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
232 if (!szFolder)
233 return ERROR_INVALID_PARAMETER;
235 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
236 if (!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));
249 if (!path)
250 return ERROR_DIRECTORY;
252 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
253 msi_free( path );
254 return r;
257 /***********************************************************************
258 * MsiGetSourcePathA (MSI.@)
260 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
261 LPSTR szPathBuf, DWORD* pcchPathBuf )
263 LPWSTR folder;
264 awstring str;
265 UINT r;
267 TRACE("%s %p %p\n", szFolder, debugstr_a(szPathBuf), pcchPathBuf);
269 str.unicode = FALSE;
270 str.str.a = szPathBuf;
272 folder = strdupAtoW( szFolder );
273 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
274 msi_free( folder );
276 return r;
279 /***********************************************************************
280 * MsiGetSourcePathW (MSI.@)
282 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
283 LPWSTR szPathBuf, DWORD* pcchPathBuf )
285 awstring str;
287 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
289 str.unicode = TRUE;
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)
310 goto end;
312 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
314 end:
315 msi_free(szwFolder);
316 msi_free(szwFolderPath);
318 return rc;
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)
329 DWORD attrib;
330 LPWSTR path = NULL;
331 LPWSTR path2 = NULL;
332 MSIFOLDER *folder;
333 MSIFILE *file;
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);
345 if (!path)
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);
360 msi_free(path2);
362 else
364 MSIFOLDER *f;
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);
375 msi_free(path2);
378 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
380 MSICOMPONENT *comp = file->Component;
381 LPWSTR p;
383 if (!comp)
384 continue;
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);
390 msi_free(p);
393 msi_free(path);
395 return ERROR_SUCCESS;
398 /***********************************************************************
399 * MsiSetTargetPathW (MSI.@)
401 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
402 LPCWSTR szFolderPath)
404 MSIPACKAGE *package;
405 UINT ret;
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);
413 if (!package)
414 return ERROR_INVALID_HANDLE;
416 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
417 msiobj_release( &package->hdr );
418 return ret;
421 /***********************************************************************
422 * MsiGetMode (MSI.@)
424 * Returns an internal installer state (if it is running in a mode iRunMode)
426 * PARAMS
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
449 * RETURNS
450 * In the state: TRUE
451 * Not in the state: FALSE
454 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
456 BOOL r = FALSE;
458 switch (iRunMode)
460 case MSIRUNMODE_WINDOWS9X:
461 if (GetVersion() & 0x80000000)
462 r = TRUE;
463 break;
465 case MSIRUNMODE_RESERVED11:
466 case MSIRUNMODE_RESERVED14:
467 case MSIRUNMODE_RESERVED15:
468 break;
470 case MSIRUNMODE_SCHEDULED:
471 case MSIRUNMODE_ROLLBACK:
472 case MSIRUNMODE_COMMIT:
473 break;
475 default:
476 FIXME("%ld %d\n", hInstall, iRunMode);
477 r = TRUE;
480 return r;
483 /***********************************************************************
484 * MsiSetMode (MSI.@)
486 BOOL WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
488 switch (iRunMode)
490 case MSIRUNMODE_RESERVED11:
491 case MSIRUNMODE_WINDOWS9X:
492 case MSIRUNMODE_RESERVED14:
493 case MSIRUNMODE_RESERVED15:
494 return FALSE;
495 default:
496 FIXME("%ld %d %d\n", hInstall, iRunMode, fState);
498 return TRUE;
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,
508 INSTALLSTATE iState)
510 LPWSTR szwFeature = NULL;
511 UINT rc;
513 szwFeature = strdupAtoW(szFeature);
515 if (!szwFeature)
516 return ERROR_FUNCTION_FAILED;
518 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
520 msi_free(szwFeature);
522 return rc;
527 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
528 INSTALLSTATE iState)
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);
536 if (!feature)
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);
555 return rc;
558 /***********************************************************************
559 * MsiSetFeatureStateW (MSI.@)
561 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
562 INSTALLSTATE iState)
564 MSIPACKAGE* package;
565 UINT rc = ERROR_SUCCESS;
567 TRACE("%s %i\n",debugstr_w(szFeature), iState);
569 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
570 if (!package)
571 return ERROR_INVALID_HANDLE;
573 rc = MSI_SetFeatureStateW(package,szFeature,iState);
575 msiobj_release( &package->hdr );
576 return rc;
579 /***********************************************************************
580 * MsiGetFeatureStateA (MSI.@)
582 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
583 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
585 LPWSTR szwFeature = NULL;
586 UINT rc;
588 szwFeature = strdupAtoW(szFeature);
590 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
592 msi_free( szwFeature);
594 return rc;
597 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
598 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
600 MSIFEATURE *feature;
602 feature = get_loaded_feature(package,szFeature);
603 if (!feature)
604 return ERROR_UNKNOWN_FEATURE;
606 if (piInstalled)
607 *piInstalled = feature->Installed;
609 if (piAction)
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, LPCWSTR szFeature,
621 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
623 MSIPACKAGE* package;
624 UINT ret;
626 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
628 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
629 if (!package)
630 return ERROR_INVALID_HANDLE;
631 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
632 msiobj_release( &package->hdr );
633 return ret;
636 /***********************************************************************
637 * MsiSetComponentStateA (MSI.@)
639 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
640 INSTALLSTATE iState)
642 UINT rc;
643 LPWSTR szwComponent = strdupAtoW(szComponent);
645 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
647 msi_free(szwComponent);
649 return rc;
652 /***********************************************************************
653 * MsiGetComponentStateA (MSI.@)
655 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
656 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
658 LPWSTR szwComponent= NULL;
659 UINT rc;
661 szwComponent= strdupAtoW(szComponent);
663 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
665 msi_free( szwComponent);
667 return rc;
670 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
671 INSTALLSTATE iState)
673 MSICOMPONENT *comp;
675 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
677 comp = get_loaded_component(package, szComponent);
678 if (!comp)
679 return ERROR_UNKNOWN_COMPONENT;
681 comp->Installed = iState;
683 return ERROR_SUCCESS;
686 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
687 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
689 MSICOMPONENT *comp;
691 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
692 piInstalled, piAction);
694 comp = get_loaded_component(package,szComponent);
695 if (!comp)
696 return ERROR_UNKNOWN_COMPONENT;
698 if (piInstalled)
699 *piInstalled = comp->Installed;
701 if (piAction)
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,
713 INSTALLSTATE iState)
715 MSIPACKAGE* package;
716 UINT ret;
718 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
719 if (!package)
720 return ERROR_INVALID_HANDLE;
721 ret = MSI_SetComponentStateW(package, szComponent, iState);
722 msiobj_release(&package->hdr);
723 return ret;
726 /***********************************************************************
727 * MsiGetComponentStateW (MSI.@)
729 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
730 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
732 MSIPACKAGE* package;
733 UINT ret;
735 TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
736 piInstalled, piAction);
738 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
739 if (!package)
740 return ERROR_INVALID_HANDLE;
741 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
742 msiobj_release( &package->hdr );
743 return ret;
746 /***********************************************************************
747 * MsiGetLanguage (MSI.@)
749 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
751 MSIPACKAGE* package;
752 LANGID langid;
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);
757 if (!package)
758 return ERROR_INVALID_HANDLE;
760 langid = msi_get_property_int( package, szProductLanguage, 0 );
761 msiobj_release( &package->hdr );
762 return langid;
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 };
770 WCHAR level[6];
771 UINT r;
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 );
785 return r;
788 /***********************************************************************
789 * MsiSetInstallLevel (MSI.@)
791 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
793 MSIPACKAGE* package;
794 UINT r;
796 TRACE("%ld %i\n", hInstall, iInstallLevel);
798 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
799 if ( !package )
800 return ERROR_INVALID_HANDLE;
802 r = MSI_SetInstallLevel( package, iInstallLevel );
804 msiobj_release( &package->hdr );
806 return r;