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