7a7dc28e998499756337ec40252edba0046d9da0
[reactos.git] / reactos / dll / win32 / msi / install.c
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2005 Aric Stewart for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 /* Msi top level apis directly related to installs */
22
23 #define WIN32_NO_STATUS
24 #define _INC_WINDOWS
25 #define COM_NO_WINDOWS_H
26
27 #define COBJMACROS
28
29 #include <stdarg.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 //#include "winerror.h"
34 #include <wine/debug.h>
35 //#include "msi.h"
36 //#include "msidefs.h"
37 #include <objbase.h>
38 #include <oleauto.h>
39
40 #include "msipriv.h"
41 #include <msiserver.h>
42 #include <wine/unicode.h>
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45
46 /***********************************************************************
47 * MsiDoActionA (MSI.@)
48 */
49 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
50 {
51 LPWSTR szwAction;
52 UINT ret;
53
54 TRACE("%s\n", debugstr_a(szAction));
55
56 szwAction = strdupAtoW(szAction);
57 if (szAction && !szwAction)
58 return ERROR_FUNCTION_FAILED;
59
60 ret = MsiDoActionW( hInstall, szwAction );
61 msi_free( szwAction );
62 return ret;
63 }
64
65 /***********************************************************************
66 * MsiDoActionW (MSI.@)
67 */
68 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
69 {
70 MSIPACKAGE *package;
71 UINT ret;
72
73 TRACE("%s\n",debugstr_w(szAction));
74
75 if (!szAction)
76 return ERROR_INVALID_PARAMETER;
77
78 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
79 if (!package)
80 {
81 HRESULT hr;
82 BSTR action;
83 IWineMsiRemotePackage *remote_package;
84
85 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
86 if (!remote_package)
87 return ERROR_INVALID_HANDLE;
88
89 action = SysAllocString( szAction );
90 if (!action)
91 {
92 IWineMsiRemotePackage_Release( remote_package );
93 return ERROR_OUTOFMEMORY;
94 }
95
96 hr = IWineMsiRemotePackage_DoAction( remote_package, action );
97
98 SysFreeString( action );
99 IWineMsiRemotePackage_Release( remote_package );
100
101 if (FAILED(hr))
102 {
103 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
104 return HRESULT_CODE(hr);
105
106 return ERROR_FUNCTION_FAILED;
107 }
108
109 return ERROR_SUCCESS;
110 }
111
112 ret = ACTION_PerformUIAction( package, szAction, SCRIPT_NONE );
113 msiobj_release( &package->hdr );
114
115 return ret;
116 }
117
118 /***********************************************************************
119 * MsiSequenceA (MSI.@)
120 */
121 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
122 {
123 LPWSTR szwTable;
124 UINT ret;
125
126 TRACE("%s, %d\n", debugstr_a(szTable), iSequenceMode);
127
128 szwTable = strdupAtoW(szTable);
129 if (szTable && !szwTable)
130 return ERROR_FUNCTION_FAILED;
131
132 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
133 msi_free( szwTable );
134 return ret;
135 }
136
137 /***********************************************************************
138 * MsiSequenceW (MSI.@)
139 */
140 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
141 {
142 MSIPACKAGE *package;
143 UINT ret;
144
145 TRACE("%s, %d\n", debugstr_w(szTable), iSequenceMode);
146
147 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
148 if (!package)
149 {
150 HRESULT hr;
151 BSTR table;
152 IWineMsiRemotePackage *remote_package;
153
154 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
155 if (!remote_package)
156 return ERROR_INVALID_HANDLE;
157
158 table = SysAllocString( szTable );
159 if (!table)
160 {
161 IWineMsiRemotePackage_Release( remote_package );
162 return ERROR_OUTOFMEMORY;
163 }
164
165 hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode );
166
167 SysFreeString( table );
168 IWineMsiRemotePackage_Release( remote_package );
169
170 if (FAILED(hr))
171 {
172 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
173 return HRESULT_CODE(hr);
174
175 return ERROR_FUNCTION_FAILED;
176 }
177
178 return ERROR_SUCCESS;
179 }
180 ret = MSI_Sequence( package, szTable );
181 msiobj_release( &package->hdr );
182 return ret;
183 }
184
185 UINT msi_strcpy_to_awstring( const WCHAR *str, int len, awstring *awbuf, DWORD *sz )
186 {
187 UINT r = ERROR_SUCCESS;
188
189 if (awbuf->str.w && !sz)
190 return ERROR_INVALID_PARAMETER;
191 if (!sz)
192 return ERROR_SUCCESS;
193
194 if (len < 0) len = strlenW( str );
195
196 if (awbuf->unicode && awbuf->str.w)
197 memcpy( awbuf->str.w, str, min(len + 1, *sz) * sizeof(WCHAR) );
198 else
199 {
200 int lenA = WideCharToMultiByte( CP_ACP, 0, str, len + 1, NULL, 0, NULL, NULL );
201 if (lenA) lenA--;
202 WideCharToMultiByte( CP_ACP, 0, str, len + 1, awbuf->str.a, *sz, NULL, NULL );
203 if (awbuf->str.a && *sz && lenA >= *sz)
204 awbuf->str.a[*sz - 1] = 0;
205 len = lenA;
206 }
207 if (awbuf->str.w && len >= *sz)
208 r = ERROR_MORE_DATA;
209 *sz = len;
210 return r;
211 }
212
213 const WCHAR *msi_get_target_folder( MSIPACKAGE *package, const WCHAR *name )
214 {
215 MSIFOLDER *folder = msi_get_loaded_folder( package, name );
216
217 if (!folder) return NULL;
218 if (!folder->ResolvedTarget)
219 {
220 MSIFOLDER *parent = folder;
221 while (parent->Parent && strcmpW( parent->Parent, parent->Directory ))
222 {
223 parent = msi_get_loaded_folder( package, parent->Parent );
224 }
225 msi_resolve_target_folder( package, parent->Directory, TRUE );
226 }
227 return folder->ResolvedTarget;
228 }
229
230 /***********************************************************************
231 * MsiGetTargetPath (internal)
232 */
233 static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
234 awstring *szPathBuf, LPDWORD pcchPathBuf )
235 {
236 MSIPACKAGE *package;
237 const WCHAR *path;
238 UINT r = ERROR_FUNCTION_FAILED;
239
240 if (!szFolder)
241 return ERROR_INVALID_PARAMETER;
242
243 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
244 if (!package)
245 {
246 HRESULT hr;
247 IWineMsiRemotePackage *remote_package;
248 LPWSTR value = NULL;
249 BSTR folder;
250 DWORD len;
251
252 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
253 if (!remote_package)
254 return ERROR_INVALID_HANDLE;
255
256 folder = SysAllocString( szFolder );
257 if (!folder)
258 {
259 IWineMsiRemotePackage_Release( remote_package );
260 return ERROR_OUTOFMEMORY;
261 }
262
263 len = 0;
264 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, NULL, &len );
265 if (FAILED(hr))
266 goto done;
267
268 len++;
269 value = msi_alloc(len * sizeof(WCHAR));
270 if (!value)
271 {
272 r = ERROR_OUTOFMEMORY;
273 goto done;
274 }
275
276 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder, value, &len );
277 if (FAILED(hr))
278 goto done;
279
280 r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
281
282 done:
283 IWineMsiRemotePackage_Release( remote_package );
284 SysFreeString( folder );
285 msi_free( value );
286
287 if (FAILED(hr))
288 {
289 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
290 return HRESULT_CODE(hr);
291
292 return ERROR_FUNCTION_FAILED;
293 }
294
295 return r;
296 }
297
298 path = msi_get_target_folder( package, szFolder );
299 msiobj_release( &package->hdr );
300
301 if (!path)
302 return ERROR_DIRECTORY;
303
304 return msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
305 }
306
307 /***********************************************************************
308 * MsiGetTargetPathA (MSI.@)
309 */
310 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
311 LPSTR szPathBuf, LPDWORD pcchPathBuf )
312 {
313 LPWSTR szwFolder;
314 awstring path;
315 UINT r;
316
317 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
318
319 szwFolder = strdupAtoW(szFolder);
320 if (szFolder && !szwFolder)
321 return ERROR_FUNCTION_FAILED;
322
323 path.unicode = FALSE;
324 path.str.a = szPathBuf;
325
326 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
327
328 msi_free( szwFolder );
329
330 return r;
331 }
332
333 /***********************************************************************
334 * MsiGetTargetPathW (MSI.@)
335 */
336 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
337 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
338 {
339 awstring path;
340
341 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
342
343 path.unicode = TRUE;
344 path.str.w = szPathBuf;
345
346 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
347 }
348
349 static WCHAR *get_source_root( MSIPACKAGE *package )
350 {
351 msi_set_sourcedir_props( package, FALSE );
352 return msi_dup_property( package->db, szSourceDir );
353 }
354
355 WCHAR *msi_resolve_source_folder( MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder )
356 {
357 MSIFOLDER *f;
358 LPWSTR p, path = NULL, parent;
359
360 TRACE("working to resolve %s\n", debugstr_w(name));
361
362 if (!strcmpW( name, szSourceDir )) name = szTargetDir;
363 if (!(f = msi_get_loaded_folder( package, name ))) return NULL;
364
365 /* special resolving for root dir */
366 if (!strcmpW( name, szTargetDir ) && !f->ResolvedSource)
367 {
368 f->ResolvedSource = get_source_root( package );
369 }
370 if (folder) *folder = f;
371 if (f->ResolvedSource)
372 {
373 path = strdupW( f->ResolvedSource );
374 TRACE(" already resolved to %s\n", debugstr_w(path));
375 return path;
376 }
377 if (!f->Parent) return path;
378 parent = f->Parent;
379 TRACE(" ! parent is %s\n", debugstr_w(parent));
380
381 p = msi_resolve_source_folder( package, parent, NULL );
382
383 if (package->WordCount & msidbSumInfoSourceTypeCompressed)
384 path = get_source_root( package );
385 else if (package->WordCount & msidbSumInfoSourceTypeSFN)
386 path = msi_build_directory_name( 3, p, f->SourceShortPath, NULL );
387 else
388 path = msi_build_directory_name( 3, p, f->SourceLongPath, NULL );
389
390 TRACE("-> %s\n", debugstr_w(path));
391 f->ResolvedSource = strdupW( path );
392 msi_free( p );
393
394 return path;
395 }
396
397 /***********************************************************************
398 * MSI_GetSourcePath (internal)
399 */
400 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
401 awstring *szPathBuf, LPDWORD pcchPathBuf )
402 {
403 MSIPACKAGE *package;
404 LPWSTR path;
405 UINT r = ERROR_FUNCTION_FAILED;
406
407 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
408
409 if (!szFolder)
410 return ERROR_INVALID_PARAMETER;
411
412 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
413 if (!package)
414 {
415 HRESULT hr;
416 IWineMsiRemotePackage *remote_package;
417 LPWSTR value = NULL;
418 BSTR folder;
419 DWORD len;
420
421 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
422 if (!remote_package)
423 return ERROR_INVALID_HANDLE;
424
425 folder = SysAllocString( szFolder );
426 if (!folder)
427 {
428 IWineMsiRemotePackage_Release( remote_package );
429 return ERROR_OUTOFMEMORY;
430 }
431
432 len = 0;
433 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, NULL, &len );
434 if (FAILED(hr))
435 goto done;
436
437 len++;
438 value = msi_alloc(len * sizeof(WCHAR));
439 if (!value)
440 {
441 r = ERROR_OUTOFMEMORY;
442 goto done;
443 }
444
445 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder, value, &len );
446 if (FAILED(hr))
447 goto done;
448
449 r = msi_strcpy_to_awstring( value, len, szPathBuf, pcchPathBuf );
450
451 done:
452 IWineMsiRemotePackage_Release( remote_package );
453 SysFreeString( folder );
454 msi_free( value );
455
456 if (FAILED(hr))
457 {
458 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
459 return HRESULT_CODE(hr);
460
461 return ERROR_FUNCTION_FAILED;
462 }
463
464 return r;
465 }
466
467 if (szPathBuf->str.w && !pcchPathBuf )
468 {
469 msiobj_release( &package->hdr );
470 return ERROR_INVALID_PARAMETER;
471 }
472
473 path = msi_resolve_source_folder( package, szFolder, NULL );
474 msiobj_release( &package->hdr );
475
476 TRACE("path = %s\n", debugstr_w(path));
477 if (!path)
478 return ERROR_DIRECTORY;
479
480 r = msi_strcpy_to_awstring( path, -1, szPathBuf, pcchPathBuf );
481 msi_free( path );
482 return r;
483 }
484
485 /***********************************************************************
486 * MsiGetSourcePathA (MSI.@)
487 */
488 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
489 LPSTR szPathBuf, LPDWORD pcchPathBuf )
490 {
491 LPWSTR folder;
492 awstring str;
493 UINT r;
494
495 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
496
497 str.unicode = FALSE;
498 str.str.a = szPathBuf;
499
500 folder = strdupAtoW( szFolder );
501 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
502 msi_free( folder );
503
504 return r;
505 }
506
507 /***********************************************************************
508 * MsiGetSourcePathW (MSI.@)
509 */
510 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
511 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
512 {
513 awstring str;
514
515 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
516
517 str.unicode = TRUE;
518 str.str.w = szPathBuf;
519
520 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
521 }
522
523 /***********************************************************************
524 * MsiSetTargetPathA (MSI.@)
525 */
526 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
527 LPCSTR szFolderPath )
528 {
529 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
530 UINT rc = ERROR_OUTOFMEMORY;
531
532 if ( !szFolder || !szFolderPath )
533 return ERROR_INVALID_PARAMETER;
534
535 szwFolder = strdupAtoW(szFolder);
536 szwFolderPath = strdupAtoW(szFolderPath);
537 if (!szwFolder || !szwFolderPath)
538 goto end;
539
540 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
541
542 end:
543 msi_free(szwFolder);
544 msi_free(szwFolderPath);
545
546 return rc;
547 }
548
549 static void set_target_path( MSIPACKAGE *package, MSIFOLDER *folder, const WCHAR *path )
550 {
551 FolderList *fl;
552 MSIFOLDER *child;
553 WCHAR *target_path;
554
555 if (!(target_path = msi_normalize_path( path ))) return;
556 if (strcmpW( target_path, folder->ResolvedTarget ))
557 {
558 msi_free( folder->ResolvedTarget );
559 folder->ResolvedTarget = target_path;
560 msi_set_property( package->db, folder->Directory, folder->ResolvedTarget, -1 );
561
562 LIST_FOR_EACH_ENTRY( fl, &folder->children, FolderList, entry )
563 {
564 child = fl->folder;
565 msi_resolve_target_folder( package, child->Directory, FALSE );
566 }
567 }
568 else msi_free( target_path );
569 }
570
571 UINT MSI_SetTargetPathW( MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath )
572 {
573 DWORD attrib;
574 MSIFOLDER *folder;
575 MSIFILE *file;
576
577 TRACE("%p %s %s\n", package, debugstr_w(szFolder), debugstr_w(szFolderPath));
578
579 attrib = GetFileAttributesW(szFolderPath);
580 /* native MSI tests writeability by making temporary files at each drive */
581 if (attrib != INVALID_FILE_ATTRIBUTES &&
582 (attrib & FILE_ATTRIBUTE_OFFLINE || attrib & FILE_ATTRIBUTE_READONLY))
583 {
584 return ERROR_FUNCTION_FAILED;
585 }
586 if (!(folder = msi_get_loaded_folder( package, szFolder ))) return ERROR_DIRECTORY;
587
588 set_target_path( package, folder, szFolderPath );
589
590 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
591 {
592 const WCHAR *dir;
593 MSICOMPONENT *comp = file->Component;
594
595 if (!comp->Enabled || (comp->assembly && !comp->assembly->application)) continue;
596
597 dir = msi_get_target_folder( package, comp->Directory );
598 msi_free( file->TargetPath );
599 file->TargetPath = msi_build_directory_name( 2, dir, file->FileName );
600 }
601 return ERROR_SUCCESS;
602 }
603
604 /***********************************************************************
605 * MsiSetTargetPathW (MSI.@)
606 */
607 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
608 LPCWSTR szFolderPath)
609 {
610 MSIPACKAGE *package;
611 UINT ret;
612
613 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
614
615 if ( !szFolder || !szFolderPath )
616 return ERROR_INVALID_PARAMETER;
617
618 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
619 if (!package)
620 {
621 HRESULT hr;
622 BSTR folder, path;
623 IWineMsiRemotePackage *remote_package;
624
625 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
626 if (!remote_package)
627 return ERROR_INVALID_HANDLE;
628
629 folder = SysAllocString( szFolder );
630 path = SysAllocString( szFolderPath );
631 if (!folder || !path)
632 {
633 SysFreeString(folder);
634 SysFreeString(path);
635 IWineMsiRemotePackage_Release( remote_package );
636 return ERROR_OUTOFMEMORY;
637 }
638
639 hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path );
640
641 SysFreeString(folder);
642 SysFreeString(path);
643 IWineMsiRemotePackage_Release( remote_package );
644
645 if (FAILED(hr))
646 {
647 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
648 return HRESULT_CODE(hr);
649
650 return ERROR_FUNCTION_FAILED;
651 }
652
653 return ERROR_SUCCESS;
654 }
655
656 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
657 msiobj_release( &package->hdr );
658 return ret;
659 }
660
661 /***********************************************************************
662 * MsiGetMode (MSI.@)
663 *
664 * Returns an internal installer state (if it is running in a mode iRunMode)
665 *
666 * PARAMS
667 * hInstall [I] Handle to the installation
668 * hRunMode [I] Checking run mode
669 * MSIRUNMODE_ADMIN Administrative mode
670 * MSIRUNMODE_ADVERTISE Advertisement mode
671 * MSIRUNMODE_MAINTENANCE Maintenance mode
672 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
673 * MSIRUNMODE_LOGENABLED Log file is writing
674 * MSIRUNMODE_OPERATIONS Operations in progress??
675 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
676 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
677 * MSIRUNMODE_CABINET Files from cabinet are installed
678 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
679 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
680 * MSIRUNMODE_RESERVED11 Reserved
681 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
682 * MSIRUNMODE_ZAWENABLED Demand installation is supported
683 * MSIRUNMODE_RESERVED14 Reserved
684 * MSIRUNMODE_RESERVED15 Reserved
685 * MSIRUNMODE_SCHEDULED called from install script
686 * MSIRUNMODE_ROLLBACK called from rollback script
687 * MSIRUNMODE_COMMIT called from commit script
688 *
689 * RETURNS
690 * In the state: TRUE
691 * Not in the state: FALSE
692 *
693 */
694 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
695 {
696 MSIPACKAGE *package;
697 BOOL r = FALSE;
698
699 TRACE("%d %d\n", hInstall, iRunMode);
700
701 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
702 if (!package)
703 {
704 BOOL ret;
705 HRESULT hr;
706 IWineMsiRemotePackage *remote_package;
707
708 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
709 if (!remote_package)
710 return FALSE;
711
712 hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret);
713 IWineMsiRemotePackage_Release(remote_package);
714
715 if (hr == S_OK)
716 return ret;
717
718 return FALSE;
719 }
720
721 switch (iRunMode)
722 {
723 case MSIRUNMODE_ADMIN:
724 FIXME("no support for administrative installs\n");
725 break;
726
727 case MSIRUNMODE_ADVERTISE:
728 FIXME("no support for advertised installs\n");
729 break;
730
731 case MSIRUNMODE_WINDOWS9X:
732 if (GetVersion() & 0x80000000)
733 r = TRUE;
734 break;
735
736 case MSIRUNMODE_OPERATIONS:
737 case MSIRUNMODE_RESERVED11:
738 case MSIRUNMODE_RESERVED14:
739 case MSIRUNMODE_RESERVED15:
740 break;
741
742 case MSIRUNMODE_SCHEDULED:
743 r = package->scheduled_action_running;
744 break;
745
746 case MSIRUNMODE_ROLLBACK:
747 r = package->rollback_action_running;
748 break;
749
750 case MSIRUNMODE_COMMIT:
751 r = package->commit_action_running;
752 break;
753
754 case MSIRUNMODE_MAINTENANCE:
755 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
756 break;
757
758 case MSIRUNMODE_ROLLBACKENABLED:
759 r = msi_get_property_int( package->db, szRollbackDisabled, 0 ) == 0;
760 break;
761
762 case MSIRUNMODE_REBOOTATEND:
763 r = package->need_reboot_at_end;
764 break;
765
766 case MSIRUNMODE_REBOOTNOW:
767 r = package->need_reboot_now;
768 break;
769
770 case MSIRUNMODE_LOGENABLED:
771 r = (package->log_file != INVALID_HANDLE_VALUE);
772 break;
773
774 default:
775 FIXME("unimplemented run mode: %d\n", iRunMode);
776 r = TRUE;
777 }
778
779 msiobj_release( &package->hdr );
780 return r;
781 }
782
783 /***********************************************************************
784 * MsiSetMode (MSI.@)
785 */
786 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
787 {
788 MSIPACKAGE *package;
789 UINT r;
790
791 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
792
793 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
794 if (!package)
795 {
796 HRESULT hr;
797 IWineMsiRemotePackage *remote_package;
798
799 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
800 if (!remote_package)
801 return FALSE;
802
803 hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState );
804 IWineMsiRemotePackage_Release( remote_package );
805
806 if (FAILED(hr))
807 {
808 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
809 return HRESULT_CODE(hr);
810
811 return ERROR_FUNCTION_FAILED;
812 }
813
814 return ERROR_SUCCESS;
815 }
816
817 switch (iRunMode)
818 {
819 case MSIRUNMODE_REBOOTATEND:
820 package->need_reboot_at_end = (fState != 0);
821 r = ERROR_SUCCESS;
822 break;
823
824 case MSIRUNMODE_REBOOTNOW:
825 package->need_reboot_now = (fState != 0);
826 r = ERROR_SUCCESS;
827 break;
828
829 default:
830 r = ERROR_ACCESS_DENIED;
831 }
832
833 msiobj_release( &package->hdr );
834 return r;
835 }
836
837 /***********************************************************************
838 * MsiSetFeatureStateA (MSI.@)
839 *
840 * According to the docs, when this is called it immediately recalculates
841 * all the component states as well
842 */
843 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
844 INSTALLSTATE iState)
845 {
846 LPWSTR szwFeature = NULL;
847 UINT rc;
848
849 szwFeature = strdupAtoW(szFeature);
850
851 if (!szwFeature)
852 return ERROR_FUNCTION_FAILED;
853
854 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
855
856 msi_free(szwFeature);
857
858 return rc;
859 }
860
861 /* update component state based on a feature change */
862 void ACTION_UpdateComponentStates( MSIPACKAGE *package, MSIFEATURE *feature )
863 {
864 INSTALLSTATE newstate;
865 ComponentList *cl;
866
867 newstate = feature->ActionRequest;
868 if (newstate == INSTALLSTATE_ABSENT) newstate = INSTALLSTATE_UNKNOWN;
869
870 LIST_FOR_EACH_ENTRY(cl, &feature->Components, ComponentList, entry)
871 {
872 MSICOMPONENT *component = cl->component;
873
874 if (!component->Enabled) continue;
875
876 TRACE("Modifying (%d): Component %s (Installed %d, Action %d, Request %d)\n",
877 newstate, debugstr_w(component->Component), component->Installed,
878 component->Action, component->ActionRequest);
879
880 if (newstate == INSTALLSTATE_LOCAL)
881 {
882 component->Action = INSTALLSTATE_LOCAL;
883 component->ActionRequest = INSTALLSTATE_LOCAL;
884 }
885 else
886 {
887 ComponentList *clist;
888 MSIFEATURE *f;
889
890 component->hasLocalFeature = FALSE;
891
892 component->Action = newstate;
893 component->ActionRequest = newstate;
894 /* if any other feature wants it local we need to set it local */
895 LIST_FOR_EACH_ENTRY(f, &package->features, MSIFEATURE, entry)
896 {
897 if ( f->ActionRequest != INSTALLSTATE_LOCAL &&
898 f->ActionRequest != INSTALLSTATE_SOURCE )
899 {
900 continue;
901 }
902 LIST_FOR_EACH_ENTRY(clist, &f->Components, ComponentList, entry)
903 {
904 if (clist->component == component &&
905 (f->ActionRequest == INSTALLSTATE_LOCAL ||
906 f->ActionRequest == INSTALLSTATE_SOURCE))
907 {
908 TRACE("Saved by %s\n", debugstr_w(f->Feature));
909 component->hasLocalFeature = TRUE;
910
911 if (component->Attributes & msidbComponentAttributesOptional)
912 {
913 if (f->Attributes & msidbFeatureAttributesFavorSource)
914 {
915 component->Action = INSTALLSTATE_SOURCE;
916 component->ActionRequest = INSTALLSTATE_SOURCE;
917 }
918 else
919 {
920 component->Action = INSTALLSTATE_LOCAL;
921 component->ActionRequest = INSTALLSTATE_LOCAL;
922 }
923 }
924 else if (component->Attributes & msidbComponentAttributesSourceOnly)
925 {
926 component->Action = INSTALLSTATE_SOURCE;
927 component->ActionRequest = INSTALLSTATE_SOURCE;
928 }
929 else
930 {
931 component->Action = INSTALLSTATE_LOCAL;
932 component->ActionRequest = INSTALLSTATE_LOCAL;
933 }
934 }
935 }
936 }
937 }
938 TRACE("Result (%d): Component %s (Installed %d, Action %d, Request %d)\n",
939 newstate, debugstr_w(component->Component), component->Installed,
940 component->Action, component->ActionRequest);
941 }
942 }
943
944 UINT MSI_SetFeatureStateW( MSIPACKAGE *package, LPCWSTR szFeature, INSTALLSTATE iState )
945 {
946 UINT rc = ERROR_SUCCESS;
947 MSIFEATURE *feature, *child;
948
949 TRACE("%s %i\n", debugstr_w(szFeature), iState);
950
951 feature = msi_get_loaded_feature( package, szFeature );
952 if (!feature)
953 return ERROR_UNKNOWN_FEATURE;
954
955 if (iState == INSTALLSTATE_ADVERTISED &&
956 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
957 return ERROR_FUNCTION_FAILED;
958
959 feature->ActionRequest = iState;
960
961 ACTION_UpdateComponentStates( package, feature );
962
963 /* update all the features that are children of this feature */
964 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
965 {
966 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
967 MSI_SetFeatureStateW(package, child->Feature, iState);
968 }
969
970 return rc;
971 }
972
973 /***********************************************************************
974 * MsiSetFeatureStateW (MSI.@)
975 */
976 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
977 INSTALLSTATE iState)
978 {
979 MSIPACKAGE* package;
980 UINT rc = ERROR_SUCCESS;
981
982 TRACE("%s %i\n",debugstr_w(szFeature), iState);
983
984 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
985 if (!package)
986 {
987 HRESULT hr;
988 BSTR feature;
989 IWineMsiRemotePackage *remote_package;
990
991 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
992 if (!remote_package)
993 return ERROR_INVALID_HANDLE;
994
995 feature = SysAllocString(szFeature);
996 if (!feature)
997 {
998 IWineMsiRemotePackage_Release(remote_package);
999 return ERROR_OUTOFMEMORY;
1000 }
1001
1002 hr = IWineMsiRemotePackage_SetFeatureState(remote_package, feature, iState);
1003
1004 SysFreeString(feature);
1005 IWineMsiRemotePackage_Release(remote_package);
1006
1007 if (FAILED(hr))
1008 {
1009 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1010 return HRESULT_CODE(hr);
1011
1012 return ERROR_FUNCTION_FAILED;
1013 }
1014
1015 return ERROR_SUCCESS;
1016 }
1017
1018 rc = MSI_SetFeatureStateW(package,szFeature,iState);
1019
1020 msiobj_release( &package->hdr );
1021 return rc;
1022 }
1023
1024 /***********************************************************************
1025 * MsiSetFeatureAttributesA (MSI.@)
1026 */
1027 UINT WINAPI MsiSetFeatureAttributesA( MSIHANDLE handle, LPCSTR feature, DWORD attrs )
1028 {
1029 UINT r;
1030 WCHAR *featureW = NULL;
1031
1032 TRACE("%u, %s, 0x%08x\n", handle, debugstr_a(feature), attrs);
1033
1034 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1035
1036 r = MsiSetFeatureAttributesW( handle, featureW, attrs );
1037 msi_free( featureW );
1038 return r;
1039 }
1040
1041 static DWORD unmap_feature_attributes( DWORD attrs )
1042 {
1043 DWORD ret = 0;
1044
1045 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORLOCAL) ret = msidbFeatureAttributesFavorLocal;
1046 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORSOURCE) ret |= msidbFeatureAttributesFavorSource;
1047 if (attrs & INSTALLFEATUREATTRIBUTE_FOLLOWPARENT) ret |= msidbFeatureAttributesFollowParent;
1048 if (attrs & INSTALLFEATUREATTRIBUTE_FAVORADVERTISE) ret |= msidbFeatureAttributesFavorAdvertise;
1049 if (attrs & INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE) ret |= msidbFeatureAttributesDisallowAdvertise;
1050 if (attrs & INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE) ret |= msidbFeatureAttributesNoUnsupportedAdvertise;
1051 return ret;
1052 }
1053
1054 /***********************************************************************
1055 * MsiSetFeatureAttributesW (MSI.@)
1056 */
1057 UINT WINAPI MsiSetFeatureAttributesW( MSIHANDLE handle, LPCWSTR name, DWORD attrs )
1058 {
1059 MSIPACKAGE *package;
1060 MSIFEATURE *feature;
1061 WCHAR *costing;
1062
1063 TRACE("%u, %s, 0x%08x\n", handle, debugstr_w(name), attrs);
1064
1065 if (!name || !name[0]) return ERROR_UNKNOWN_FEATURE;
1066
1067 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1068 return ERROR_INVALID_HANDLE;
1069
1070 costing = msi_dup_property( package->db, szCostingComplete );
1071 if (!costing || !strcmpW( costing, szOne ))
1072 {
1073 msi_free( costing );
1074 msiobj_release( &package->hdr );
1075 return ERROR_FUNCTION_FAILED;
1076 }
1077 msi_free( costing );
1078 if (!(feature = msi_get_loaded_feature( package, name )))
1079 {
1080 msiobj_release( &package->hdr );
1081 return ERROR_UNKNOWN_FEATURE;
1082 }
1083 feature->Attributes = unmap_feature_attributes( attrs );
1084 msiobj_release( &package->hdr );
1085 return ERROR_SUCCESS;
1086 }
1087
1088 /***********************************************************************
1089 * MsiGetFeatureStateA (MSI.@)
1090 */
1091 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
1092 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1093 {
1094 LPWSTR szwFeature = NULL;
1095 UINT rc;
1096
1097 if (szFeature && !(szwFeature = strdupAtoW(szFeature))) return ERROR_OUTOFMEMORY;
1098
1099 rc = MsiGetFeatureStateW(hInstall, szwFeature, piInstalled, piAction);
1100 msi_free( szwFeature);
1101 return rc;
1102 }
1103
1104 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
1105 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1106 {
1107 MSIFEATURE *feature;
1108
1109 feature = msi_get_loaded_feature(package,szFeature);
1110 if (!feature)
1111 return ERROR_UNKNOWN_FEATURE;
1112
1113 if (piInstalled)
1114 *piInstalled = feature->Installed;
1115
1116 if (piAction)
1117 *piAction = feature->ActionRequest;
1118
1119 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
1120
1121 return ERROR_SUCCESS;
1122 }
1123
1124 /***********************************************************************
1125 * MsiGetFeatureStateW (MSI.@)
1126 */
1127 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
1128 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1129 {
1130 MSIPACKAGE* package;
1131 UINT ret;
1132
1133 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
1134
1135 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1136 if (!package)
1137 {
1138 HRESULT hr;
1139 BSTR feature;
1140 IWineMsiRemotePackage *remote_package;
1141
1142 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1143 if (!remote_package)
1144 return ERROR_INVALID_HANDLE;
1145
1146 feature = SysAllocString(szFeature);
1147 if (!feature)
1148 {
1149 IWineMsiRemotePackage_Release(remote_package);
1150 return ERROR_OUTOFMEMORY;
1151 }
1152
1153 hr = IWineMsiRemotePackage_GetFeatureState(remote_package, feature,
1154 piInstalled, piAction);
1155
1156 SysFreeString(feature);
1157 IWineMsiRemotePackage_Release(remote_package);
1158
1159 if (FAILED(hr))
1160 {
1161 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1162 return HRESULT_CODE(hr);
1163
1164 return ERROR_FUNCTION_FAILED;
1165 }
1166
1167 return ERROR_SUCCESS;
1168 }
1169
1170 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
1171 msiobj_release( &package->hdr );
1172 return ret;
1173 }
1174
1175 /***********************************************************************
1176 * MsiGetFeatureCostA (MSI.@)
1177 */
1178 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
1179 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1180 {
1181 LPWSTR szwFeature = NULL;
1182 UINT rc;
1183
1184 szwFeature = strdupAtoW(szFeature);
1185
1186 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
1187
1188 msi_free(szwFeature);
1189
1190 return rc;
1191 }
1192
1193 static INT feature_cost( MSIFEATURE *feature )
1194 {
1195 INT cost = 0;
1196 MSICOMPONENT *comp;
1197
1198 LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry )
1199 {
1200 cost += comp->Cost;
1201 }
1202 return cost;
1203 }
1204
1205 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1206 INSTALLSTATE state, LPINT cost )
1207 {
1208 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1209
1210 *cost = 0;
1211 switch (tree)
1212 {
1213 case MSICOSTTREE_CHILDREN:
1214 {
1215 MSIFEATURE *child;
1216
1217 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1218 {
1219 if (child->ActionRequest == state)
1220 *cost += feature_cost( child );
1221 }
1222 break;
1223 }
1224 case MSICOSTTREE_PARENTS:
1225 {
1226 const WCHAR *feature_parent = feature->Feature_Parent;
1227 for (;;)
1228 {
1229 MSIFEATURE *parent = msi_get_loaded_feature( package, feature_parent );
1230 if (!parent)
1231 break;
1232
1233 if (parent->ActionRequest == state)
1234 *cost += feature_cost( parent );
1235
1236 feature_parent = parent->Feature_Parent;
1237 }
1238 break;
1239 }
1240 case MSICOSTTREE_SELFONLY:
1241 if (feature->ActionRequest == state)
1242 *cost = feature_cost( feature );
1243 break;
1244
1245 default:
1246 WARN("unhandled cost tree %u\n", tree);
1247 break;
1248 }
1249
1250 *cost /= 512;
1251 return ERROR_SUCCESS;
1252 }
1253
1254 /***********************************************************************
1255 * MsiGetFeatureCostW (MSI.@)
1256 */
1257 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1258 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1259 {
1260 MSIPACKAGE *package;
1261 MSIFEATURE *feature;
1262 UINT ret;
1263
1264 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1265 iCostTree, iState, piCost);
1266
1267 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1268 if (!package)
1269 {
1270 HRESULT hr;
1271 BSTR feature;
1272 IWineMsiRemotePackage *remote_package;
1273
1274 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1275 if (!remote_package)
1276 return ERROR_INVALID_HANDLE;
1277
1278 feature = SysAllocString(szFeature);
1279 if (!feature)
1280 {
1281 IWineMsiRemotePackage_Release(remote_package);
1282 return ERROR_OUTOFMEMORY;
1283 }
1284
1285 hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
1286 iCostTree, iState, piCost);
1287
1288 SysFreeString(feature);
1289 IWineMsiRemotePackage_Release(remote_package);
1290
1291 if (FAILED(hr))
1292 {
1293 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1294 return HRESULT_CODE(hr);
1295
1296 return ERROR_FUNCTION_FAILED;
1297 }
1298
1299 return ERROR_SUCCESS;
1300 }
1301
1302 feature = msi_get_loaded_feature(package, szFeature);
1303
1304 if (feature)
1305 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1306 else
1307 ret = ERROR_UNKNOWN_FEATURE;
1308
1309 msiobj_release( &package->hdr );
1310 return ret;
1311 }
1312
1313 /***********************************************************************
1314 * MsiGetFeatureInfoA (MSI.@)
1315 */
1316 UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
1317 LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
1318 {
1319 UINT r;
1320 WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
1321
1322 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
1323 title_len, help, help_len);
1324
1325 if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
1326
1327 if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
1328 {
1329 msi_free( featureW );
1330 return ERROR_OUTOFMEMORY;
1331 }
1332 if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
1333 {
1334 msi_free( featureW );
1335 msi_free( titleW );
1336 return ERROR_OUTOFMEMORY;
1337 }
1338 r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
1339 if (r == ERROR_SUCCESS)
1340 {
1341 if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
1342 if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
1343 }
1344 msi_free( titleW );
1345 msi_free( helpW );
1346 msi_free( featureW );
1347 return r;
1348 }
1349
1350 static DWORD map_feature_attributes( DWORD attrs )
1351 {
1352 DWORD ret = 0;
1353
1354 if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
1355 if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
1356 if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
1357 if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
1358 if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
1359 if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
1360 return ret;
1361 }
1362
1363 static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
1364 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1365 {
1366 UINT r = ERROR_SUCCESS;
1367 MSIFEATURE *feature = msi_get_loaded_feature( package, name );
1368 int len;
1369
1370 if (!feature) return ERROR_UNKNOWN_FEATURE;
1371 if (attrs) *attrs = map_feature_attributes( feature->Attributes );
1372 if (title_len)
1373 {
1374 if (feature->Title) len = strlenW( feature->Title );
1375 else len = 0;
1376 if (*title_len <= len)
1377 {
1378 *title_len = len;
1379 if (title) r = ERROR_MORE_DATA;
1380 }
1381 else if (title)
1382 {
1383 if (feature->Title) strcpyW( title, feature->Title );
1384 else *title = 0;
1385 *title_len = len;
1386 }
1387 }
1388 if (help_len)
1389 {
1390 if (feature->Description) len = strlenW( feature->Description );
1391 else len = 0;
1392 if (*help_len <= len)
1393 {
1394 *help_len = len;
1395 if (help) r = ERROR_MORE_DATA;
1396 }
1397 else if (help)
1398 {
1399 if (feature->Description) strcpyW( help, feature->Description );
1400 else *help = 0;
1401 *help_len = len;
1402 }
1403 }
1404 return r;
1405 }
1406
1407 /***********************************************************************
1408 * MsiGetFeatureInfoW (MSI.@)
1409 */
1410 UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
1411 LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
1412 {
1413 UINT r;
1414 MSIPACKAGE *package;
1415
1416 TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
1417 title_len, help, help_len);
1418
1419 if (!feature) return ERROR_INVALID_PARAMETER;
1420
1421 if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
1422 return ERROR_INVALID_HANDLE;
1423
1424 /* features may not have been loaded yet */
1425 msi_load_all_components( package );
1426 msi_load_all_features( package );
1427
1428 r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
1429 msiobj_release( &package->hdr );
1430 return r;
1431 }
1432
1433 /***********************************************************************
1434 * MsiSetComponentStateA (MSI.@)
1435 */
1436 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1437 INSTALLSTATE iState)
1438 {
1439 UINT rc;
1440 LPWSTR szwComponent = strdupAtoW(szComponent);
1441
1442 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1443
1444 msi_free(szwComponent);
1445
1446 return rc;
1447 }
1448
1449 /***********************************************************************
1450 * MsiGetComponentStateA (MSI.@)
1451 */
1452 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1453 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1454 {
1455 LPWSTR szwComponent= NULL;
1456 UINT rc;
1457
1458 szwComponent= strdupAtoW(szComponent);
1459
1460 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1461
1462 msi_free( szwComponent);
1463
1464 return rc;
1465 }
1466
1467 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1468 INSTALLSTATE iState)
1469 {
1470 MSICOMPONENT *comp;
1471
1472 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1473
1474 comp = msi_get_loaded_component(package, szComponent);
1475 if (!comp)
1476 return ERROR_UNKNOWN_COMPONENT;
1477
1478 if (comp->Enabled)
1479 comp->Action = iState;
1480
1481 return ERROR_SUCCESS;
1482 }
1483
1484 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1485 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1486 {
1487 MSICOMPONENT *comp;
1488
1489 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1490 piInstalled, piAction);
1491
1492 comp = msi_get_loaded_component(package,szComponent);
1493 if (!comp)
1494 return ERROR_UNKNOWN_COMPONENT;
1495
1496 if (piInstalled)
1497 {
1498 if (comp->Enabled)
1499 *piInstalled = comp->Installed;
1500 else
1501 *piInstalled = INSTALLSTATE_UNKNOWN;
1502 }
1503
1504 if (piAction)
1505 {
1506 if (comp->Enabled)
1507 *piAction = comp->Action;
1508 else
1509 *piAction = INSTALLSTATE_UNKNOWN;
1510 }
1511
1512 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1513 return ERROR_SUCCESS;
1514 }
1515
1516 /***********************************************************************
1517 * MsiSetComponentStateW (MSI.@)
1518 */
1519 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1520 INSTALLSTATE iState)
1521 {
1522 MSIPACKAGE* package;
1523 UINT ret;
1524
1525 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1526 if (!package)
1527 {
1528 HRESULT hr;
1529 BSTR component;
1530 IWineMsiRemotePackage *remote_package;
1531
1532 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1533 if (!remote_package)
1534 return ERROR_INVALID_HANDLE;
1535
1536 component = SysAllocString(szComponent);
1537 if (!component)
1538 {
1539 IWineMsiRemotePackage_Release(remote_package);
1540 return ERROR_OUTOFMEMORY;
1541 }
1542
1543 hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState);
1544
1545 SysFreeString(component);
1546 IWineMsiRemotePackage_Release(remote_package);
1547
1548 if (FAILED(hr))
1549 {
1550 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1551 return HRESULT_CODE(hr);
1552
1553 return ERROR_FUNCTION_FAILED;
1554 }
1555
1556 return ERROR_SUCCESS;
1557 }
1558
1559 ret = MSI_SetComponentStateW(package, szComponent, iState);
1560 msiobj_release(&package->hdr);
1561 return ret;
1562 }
1563
1564 /***********************************************************************
1565 * MsiGetComponentStateW (MSI.@)
1566 */
1567 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1568 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1569 {
1570 MSIPACKAGE* package;
1571 UINT ret;
1572
1573 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1574 piInstalled, piAction);
1575
1576 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1577 if (!package)
1578 {
1579 HRESULT hr;
1580 BSTR component;
1581 IWineMsiRemotePackage *remote_package;
1582
1583 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1584 if (!remote_package)
1585 return ERROR_INVALID_HANDLE;
1586
1587 component = SysAllocString(szComponent);
1588 if (!component)
1589 {
1590 IWineMsiRemotePackage_Release(remote_package);
1591 return ERROR_OUTOFMEMORY;
1592 }
1593
1594 hr = IWineMsiRemotePackage_GetComponentState(remote_package, component,
1595 piInstalled, piAction);
1596
1597 SysFreeString(component);
1598 IWineMsiRemotePackage_Release(remote_package);
1599
1600 if (FAILED(hr))
1601 {
1602 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1603 return HRESULT_CODE(hr);
1604
1605 return ERROR_FUNCTION_FAILED;
1606 }
1607
1608 return ERROR_SUCCESS;
1609 }
1610
1611 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1612 msiobj_release( &package->hdr );
1613 return ret;
1614 }
1615
1616 /***********************************************************************
1617 * MsiGetLanguage (MSI.@)
1618 */
1619 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1620 {
1621 MSIPACKAGE* package;
1622 LANGID langid;
1623
1624 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1625 if (!package)
1626 {
1627 HRESULT hr;
1628 LANGID lang;
1629 IWineMsiRemotePackage *remote_package;
1630
1631 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1632 if (!remote_package)
1633 return ERROR_INVALID_HANDLE;
1634
1635 hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang);
1636
1637 if (SUCCEEDED(hr))
1638 return lang;
1639
1640 return 0;
1641 }
1642
1643 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1644 msiobj_release( &package->hdr );
1645 return langid;
1646 }
1647
1648 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1649 {
1650 static const WCHAR fmt[] = { '%','d',0 };
1651 WCHAR level[6];
1652 int len;
1653 UINT r;
1654
1655 TRACE("%p %i\n", package, iInstallLevel);
1656
1657 if (iInstallLevel > 32767)
1658 return ERROR_INVALID_PARAMETER;
1659
1660 if (iInstallLevel < 1)
1661 return MSI_SetFeatureStates( package );
1662
1663 len = sprintfW( level, fmt, iInstallLevel );
1664 r = msi_set_property( package->db, szInstallLevel, level, len );
1665 if ( r == ERROR_SUCCESS )
1666 r = MSI_SetFeatureStates( package );
1667
1668 return r;
1669 }
1670
1671 /***********************************************************************
1672 * MsiSetInstallLevel (MSI.@)
1673 */
1674 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1675 {
1676 MSIPACKAGE* package;
1677 UINT r;
1678
1679 TRACE("%d %i\n", hInstall, iInstallLevel);
1680
1681 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1682 if (!package)
1683 {
1684 HRESULT hr;
1685 IWineMsiRemotePackage *remote_package;
1686
1687 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1688 if (!remote_package)
1689 return ERROR_INVALID_HANDLE;
1690
1691 hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel);
1692
1693 IWineMsiRemotePackage_Release(remote_package);
1694
1695 if (FAILED(hr))
1696 {
1697 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1698 return HRESULT_CODE(hr);
1699
1700 return ERROR_FUNCTION_FAILED;
1701 }
1702
1703 return ERROR_SUCCESS;
1704 }
1705
1706 r = MSI_SetInstallLevel( package, iInstallLevel );
1707
1708 msiobj_release( &package->hdr );
1709
1710 return r;
1711 }
1712
1713 /***********************************************************************
1714 * MsiGetFeatureValidStatesW (MSI.@)
1715 */
1716 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1717 LPDWORD pInstallState)
1718 {
1719 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1720 FIXME("%d %s %p stub returning %d\n",
1721 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1722
1723 return ERROR_SUCCESS;
1724 }
1725
1726 /***********************************************************************
1727 * MsiGetFeatureValidStatesA (MSI.@)
1728 */
1729 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1730 LPDWORD pInstallState)
1731 {
1732 UINT ret;
1733 LPWSTR szwFeature = strdupAtoW(szFeature);
1734
1735 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1736
1737 msi_free(szwFeature);
1738
1739 return ret;
1740 }