[msi]
[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 COBJMACROS
24
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msidefs.h"
33 #include "objbase.h"
34 #include "oleauto.h"
35
36 #include "msipriv.h"
37 #include "msiserver.h"
38 #include "wine/unicode.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(msi);
41
42 /***********************************************************************
43 * MsiDoActionA (MSI.@)
44 */
45 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
46 {
47 LPWSTR szwAction;
48 UINT ret;
49
50 TRACE("%s\n", debugstr_a(szAction));
51
52 szwAction = strdupAtoW(szAction);
53 if (szAction && !szwAction)
54 return ERROR_FUNCTION_FAILED;
55
56 ret = MsiDoActionW( hInstall, szwAction );
57 msi_free( szwAction );
58 return ret;
59 }
60
61 /***********************************************************************
62 * MsiDoActionW (MSI.@)
63 */
64 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
65 {
66 MSIPACKAGE *package;
67 UINT ret;
68
69 TRACE("%s\n",debugstr_w(szAction));
70
71 if (!szAction)
72 return ERROR_INVALID_PARAMETER;
73
74 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
75 if (!package)
76 {
77 HRESULT hr;
78 BSTR action;
79 IWineMsiRemotePackage *remote_package;
80
81 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
82 if (!remote_package)
83 return ERROR_INVALID_HANDLE;
84
85 action = SysAllocString( szAction );
86 if (!action)
87 {
88 IWineMsiRemotePackage_Release( remote_package );
89 return ERROR_OUTOFMEMORY;
90 }
91
92 hr = IWineMsiRemotePackage_DoAction( remote_package, action );
93
94 SysFreeString( action );
95 IWineMsiRemotePackage_Release( remote_package );
96
97 if (FAILED(hr))
98 {
99 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
100 return HRESULT_CODE(hr);
101
102 return ERROR_FUNCTION_FAILED;
103 }
104
105 return ERROR_SUCCESS;
106 }
107
108 ret = ACTION_PerformUIAction( package, szAction, -1 );
109 msiobj_release( &package->hdr );
110
111 return ret;
112 }
113
114 /***********************************************************************
115 * MsiSequenceA (MSI.@)
116 */
117 UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
118 {
119 LPWSTR szwTable;
120 UINT ret;
121
122 TRACE("%s\n", debugstr_a(szTable));
123
124 szwTable = strdupAtoW(szTable);
125 if (szTable && !szwTable)
126 return ERROR_FUNCTION_FAILED;
127
128 ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
129 msi_free( szwTable );
130 return ret;
131 }
132
133 /***********************************************************************
134 * MsiSequenceW (MSI.@)
135 */
136 UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
137 {
138 MSIPACKAGE *package;
139 UINT ret;
140
141 TRACE("%s\n", debugstr_w(szTable));
142
143 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
144 if (!package)
145 {
146 HRESULT hr;
147 BSTR table;
148 IWineMsiRemotePackage *remote_package;
149
150 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
151 if (!remote_package)
152 return ERROR_INVALID_HANDLE;
153
154 table = SysAllocString( szTable );
155 if (!table)
156 {
157 IWineMsiRemotePackage_Release( remote_package );
158 return ERROR_OUTOFMEMORY;
159 }
160
161 hr = IWineMsiRemotePackage_Sequence( remote_package, table, iSequenceMode );
162
163 SysFreeString( table );
164 IWineMsiRemotePackage_Release( remote_package );
165
166 if (FAILED(hr))
167 {
168 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
169 return HRESULT_CODE(hr);
170
171 return ERROR_FUNCTION_FAILED;
172 }
173
174 return ERROR_SUCCESS;
175 }
176
177 ret = MSI_Sequence( package, szTable, iSequenceMode );
178 msiobj_release( &package->hdr );
179
180 return ret;
181 }
182
183 UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
184 {
185 UINT len, r = ERROR_SUCCESS;
186
187 if (awbuf->str.w && !sz )
188 return ERROR_INVALID_PARAMETER;
189
190 if (!sz)
191 return r;
192
193 if (awbuf->unicode)
194 {
195 len = lstrlenW( str );
196 if (awbuf->str.w)
197 lstrcpynW( awbuf->str.w, str, *sz );
198 }
199 else
200 {
201 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
202 if (len)
203 len--;
204 WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
205 if ( awbuf->str.a && *sz && (len >= *sz) )
206 awbuf->str.a[*sz - 1] = 0;
207 }
208
209 if (awbuf->str.w && len >= *sz)
210 r = ERROR_MORE_DATA;
211 *sz = len;
212 return r;
213 }
214
215 /***********************************************************************
216 * MsiGetTargetPath (internal)
217 */
218 static UINT MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
219 awstring *szPathBuf, LPDWORD pcchPathBuf )
220 {
221 MSIPACKAGE *package;
222 LPWSTR path;
223 UINT r = ERROR_FUNCTION_FAILED;
224
225 if (!szFolder)
226 return ERROR_INVALID_PARAMETER;
227
228 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
229 if (!package)
230 {
231 HRESULT hr;
232 IWineMsiRemotePackage *remote_package;
233 LPWSTR value = NULL;
234 BSTR folder;
235 DWORD len;
236
237 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
238 if (!remote_package)
239 return ERROR_INVALID_HANDLE;
240
241 folder = SysAllocString( szFolder );
242 if (!folder)
243 {
244 IWineMsiRemotePackage_Release( remote_package );
245 return ERROR_OUTOFMEMORY;
246 }
247
248 len = 0;
249 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
250 NULL, &len );
251 if (FAILED(hr))
252 goto done;
253
254 len++;
255 value = msi_alloc(len * sizeof(WCHAR));
256 if (!value)
257 {
258 r = ERROR_OUTOFMEMORY;
259 goto done;
260 }
261
262 hr = IWineMsiRemotePackage_GetTargetPath( remote_package, folder,
263 (BSTR *)value, &len);
264 if (FAILED(hr))
265 goto done;
266
267 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
268
269 done:
270 IWineMsiRemotePackage_Release( remote_package );
271 SysFreeString( folder );
272 msi_free( value );
273
274 if (FAILED(hr))
275 {
276 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
277 return HRESULT_CODE(hr);
278
279 return ERROR_FUNCTION_FAILED;
280 }
281
282 return r;
283 }
284
285 path = resolve_target_folder( package, szFolder, FALSE, TRUE, NULL );
286 msiobj_release( &package->hdr );
287
288 if (!path)
289 return ERROR_DIRECTORY;
290
291 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
292 msi_free( path );
293 return r;
294 }
295
296 /***********************************************************************
297 * MsiGetTargetPathA (MSI.@)
298 */
299 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
300 LPSTR szPathBuf, LPDWORD pcchPathBuf )
301 {
302 LPWSTR szwFolder;
303 awstring path;
304 UINT r;
305
306 TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
307
308 szwFolder = strdupAtoW(szFolder);
309 if (szFolder && !szwFolder)
310 return ERROR_FUNCTION_FAILED;
311
312 path.unicode = FALSE;
313 path.str.a = szPathBuf;
314
315 r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
316
317 msi_free( szwFolder );
318
319 return r;
320 }
321
322 /***********************************************************************
323 * MsiGetTargetPathW (MSI.@)
324 */
325 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
326 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
327 {
328 awstring path;
329
330 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
331
332 path.unicode = TRUE;
333 path.str.w = szPathBuf;
334
335 return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
336 }
337
338 /***********************************************************************
339 * MSI_GetSourcePath (internal)
340 */
341 static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
342 awstring *szPathBuf, LPDWORD pcchPathBuf )
343 {
344 MSIPACKAGE *package;
345 LPWSTR path;
346 UINT r = ERROR_FUNCTION_FAILED;
347
348 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
349
350 if (!szFolder)
351 return ERROR_INVALID_PARAMETER;
352
353 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
354 if (!package)
355 {
356 HRESULT hr;
357 IWineMsiRemotePackage *remote_package;
358 LPWSTR value = NULL;
359 BSTR folder;
360 DWORD len;
361
362 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
363 if (!remote_package)
364 return ERROR_INVALID_HANDLE;
365
366 folder = SysAllocString( szFolder );
367 if (!folder)
368 {
369 IWineMsiRemotePackage_Release( remote_package );
370 return ERROR_OUTOFMEMORY;
371 }
372
373 len = 0;
374 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
375 NULL, &len );
376 if (FAILED(hr))
377 goto done;
378
379 len++;
380 value = msi_alloc(len * sizeof(WCHAR));
381 if (!value)
382 {
383 r = ERROR_OUTOFMEMORY;
384 goto done;
385 }
386
387 hr = IWineMsiRemotePackage_GetSourcePath( remote_package, folder,
388 (BSTR *)value, &len);
389 if (FAILED(hr))
390 goto done;
391
392 r = msi_strcpy_to_awstring( value, szPathBuf, pcchPathBuf );
393
394 done:
395 IWineMsiRemotePackage_Release( remote_package );
396 SysFreeString( folder );
397 msi_free( value );
398
399 if (FAILED(hr))
400 {
401 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
402 return HRESULT_CODE(hr);
403
404 return ERROR_FUNCTION_FAILED;
405 }
406
407 return r;
408 }
409
410 if (szPathBuf->str.w && !pcchPathBuf )
411 {
412 msiobj_release( &package->hdr );
413 return ERROR_INVALID_PARAMETER;
414 }
415
416 path = resolve_source_folder( package, szFolder, NULL );
417 msiobj_release( &package->hdr );
418
419 TRACE("path = %s\n", debugstr_w(path));
420 if (!path)
421 return ERROR_DIRECTORY;
422
423 r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
424 msi_free( path );
425 return r;
426 }
427
428 /***********************************************************************
429 * MsiGetSourcePathA (MSI.@)
430 */
431 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder,
432 LPSTR szPathBuf, LPDWORD pcchPathBuf )
433 {
434 LPWSTR folder;
435 awstring str;
436 UINT r;
437
438 TRACE("%s %p %p\n", szFolder, debugstr_a(szPathBuf), pcchPathBuf);
439
440 str.unicode = FALSE;
441 str.str.a = szPathBuf;
442
443 folder = strdupAtoW( szFolder );
444 r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
445 msi_free( folder );
446
447 return r;
448 }
449
450 /***********************************************************************
451 * MsiGetSourcePathW (MSI.@)
452 */
453 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
454 LPWSTR szPathBuf, LPDWORD pcchPathBuf )
455 {
456 awstring str;
457
458 TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
459
460 str.unicode = TRUE;
461 str.str.w = szPathBuf;
462
463 return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
464 }
465
466 /***********************************************************************
467 * MsiSetTargetPathA (MSI.@)
468 */
469 UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
470 LPCSTR szFolderPath )
471 {
472 LPWSTR szwFolder = NULL, szwFolderPath = NULL;
473 UINT rc = ERROR_OUTOFMEMORY;
474
475 if ( !szFolder || !szFolderPath )
476 return ERROR_INVALID_PARAMETER;
477
478 szwFolder = strdupAtoW(szFolder);
479 szwFolderPath = strdupAtoW(szFolderPath);
480 if (!szwFolder || !szwFolderPath)
481 goto end;
482
483 rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
484
485 end:
486 msi_free(szwFolder);
487 msi_free(szwFolderPath);
488
489 return rc;
490 }
491
492 /*
493 * Ok my original interpretation of this was wrong. And it looks like msdn has
494 * changed a bit also. The given folder path does not have to actually already
495 * exist, it just cannot be read only and must be a legal folder path.
496 */
497 UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder,
498 LPCWSTR szFolderPath)
499 {
500 DWORD attrib;
501 LPWSTR path = NULL;
502 LPWSTR path2 = NULL;
503 MSIFOLDER *folder;
504 MSIFILE *file;
505
506 TRACE("%p %s %s\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
507
508 attrib = GetFileAttributesW(szFolderPath);
509 /* native MSI tests writeability by making temporary files at each drive */
510 if ( attrib != INVALID_FILE_ATTRIBUTES &&
511 (attrib & FILE_ATTRIBUTE_OFFLINE ||
512 attrib & FILE_ATTRIBUTE_READONLY))
513 return ERROR_FUNCTION_FAILED;
514
515 path = resolve_target_folder( package, szFolder, FALSE, FALSE, &folder );
516 if (!path)
517 return ERROR_DIRECTORY;
518
519 msi_free(folder->Property);
520 folder->Property = build_directory_name(2, szFolderPath, NULL);
521
522 if (!strcmpiW( path, folder->Property ))
523 {
524 /*
525 * Resolved Target has not really changed, so just
526 * set this folder and do not recalculate everything.
527 */
528 msi_free(folder->ResolvedTarget);
529 folder->ResolvedTarget = NULL;
530 path2 = resolve_target_folder( package, szFolder, TRUE, FALSE, NULL );
531 msi_free(path2);
532 }
533 else
534 {
535 MSIFOLDER *f;
536
537 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
538 {
539 msi_free(f->ResolvedTarget);
540 f->ResolvedTarget=NULL;
541 }
542
543 LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
544 {
545 path2 = resolve_target_folder( package, f->Directory, TRUE, FALSE, NULL );
546 msi_free(path2);
547 }
548
549 LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
550 {
551 MSICOMPONENT *comp = file->Component;
552 LPWSTR dir;
553
554 if (!comp->Enabled || (comp->assembly && !comp->assembly->application))
555 continue;
556
557 dir = resolve_target_folder( package, comp->Directory, FALSE, FALSE, NULL );
558 msi_free(file->TargetPath);
559
560 file->TargetPath = build_directory_name(2, dir, file->FileName);
561 msi_free(dir);
562 }
563 }
564 msi_free(path);
565
566 return ERROR_SUCCESS;
567 }
568
569 /***********************************************************************
570 * MsiSetTargetPathW (MSI.@)
571 */
572 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder,
573 LPCWSTR szFolderPath)
574 {
575 MSIPACKAGE *package;
576 UINT ret;
577
578 TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
579
580 if ( !szFolder || !szFolderPath )
581 return ERROR_INVALID_PARAMETER;
582
583 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
584 if (!package)
585 {
586 HRESULT hr;
587 BSTR folder, path;
588 IWineMsiRemotePackage *remote_package;
589
590 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
591 if (!remote_package)
592 return ERROR_INVALID_HANDLE;
593
594 folder = SysAllocString( szFolder );
595 path = SysAllocString( szFolderPath );
596 if (!folder || !path)
597 {
598 SysFreeString(folder);
599 SysFreeString(path);
600 IWineMsiRemotePackage_Release( remote_package );
601 return ERROR_OUTOFMEMORY;
602 }
603
604 hr = IWineMsiRemotePackage_SetTargetPath( remote_package, folder, path );
605
606 SysFreeString(folder);
607 SysFreeString(path);
608 IWineMsiRemotePackage_Release( remote_package );
609
610 if (FAILED(hr))
611 {
612 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
613 return HRESULT_CODE(hr);
614
615 return ERROR_FUNCTION_FAILED;
616 }
617
618 return ERROR_SUCCESS;
619 }
620
621 ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
622 msiobj_release( &package->hdr );
623 return ret;
624 }
625
626 /***********************************************************************
627 * MsiGetMode (MSI.@)
628 *
629 * Returns an internal installer state (if it is running in a mode iRunMode)
630 *
631 * PARAMS
632 * hInstall [I] Handle to the installation
633 * hRunMode [I] Checking run mode
634 * MSIRUNMODE_ADMIN Administrative mode
635 * MSIRUNMODE_ADVERTISE Advertisement mode
636 * MSIRUNMODE_MAINTENANCE Maintenance mode
637 * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled
638 * MSIRUNMODE_LOGENABLED Log file is writing
639 * MSIRUNMODE_OPERATIONS Operations in progress??
640 * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed
641 * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation
642 * MSIRUNMODE_CABINET Files from cabinet are installed
643 * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is suppressed
644 * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is suppressed
645 * MSIRUNMODE_RESERVED11 Reserved
646 * MSIRUNMODE_WINDOWS9X Running under Windows95/98
647 * MSIRUNMODE_ZAWENABLED Demand installation is supported
648 * MSIRUNMODE_RESERVED14 Reserved
649 * MSIRUNMODE_RESERVED15 Reserved
650 * MSIRUNMODE_SCHEDULED called from install script
651 * MSIRUNMODE_ROLLBACK called from rollback script
652 * MSIRUNMODE_COMMIT called from commit script
653 *
654 * RETURNS
655 * In the state: TRUE
656 * Not in the state: FALSE
657 *
658 */
659 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
660 {
661 MSIPACKAGE *package;
662 BOOL r = FALSE;
663
664 TRACE("%d %d\n", hInstall, iRunMode);
665
666 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
667 if (!package)
668 {
669 BOOL ret;
670 HRESULT hr;
671 IWineMsiRemotePackage *remote_package;
672
673 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
674 if (!remote_package)
675 return FALSE;
676
677 hr = IWineMsiRemotePackage_GetMode(remote_package, iRunMode, &ret);
678 IWineMsiRemotePackage_Release(remote_package);
679
680 if (hr == S_OK)
681 return ret;
682
683 return FALSE;
684 }
685
686 switch (iRunMode)
687 {
688 case MSIRUNMODE_WINDOWS9X:
689 if (GetVersion() & 0x80000000)
690 r = TRUE;
691 break;
692
693 case MSIRUNMODE_OPERATIONS:
694 case MSIRUNMODE_RESERVED11:
695 case MSIRUNMODE_RESERVED14:
696 case MSIRUNMODE_RESERVED15:
697 break;
698
699 case MSIRUNMODE_SCHEDULED:
700 r = package->scheduled_action_running;
701 break;
702
703 case MSIRUNMODE_ROLLBACK:
704 r = package->rollback_action_running;
705 break;
706
707 case MSIRUNMODE_COMMIT:
708 r = package->commit_action_running;
709 break;
710
711 case MSIRUNMODE_MAINTENANCE:
712 r = msi_get_property_int( package->db, szInstalled, 0 ) != 0;
713 break;
714
715 case MSIRUNMODE_REBOOTATEND:
716 r = package->need_reboot;
717 break;
718
719 case MSIRUNMODE_LOGENABLED:
720 r = (package->log_file != INVALID_HANDLE_VALUE);
721 break;
722
723 default:
724 FIXME("unimplemented run mode: %d\n", iRunMode);
725 r = TRUE;
726 }
727
728 msiobj_release( &package->hdr );
729 return r;
730 }
731
732 /***********************************************************************
733 * MsiSetMode (MSI.@)
734 */
735 UINT WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
736 {
737 MSIPACKAGE *package;
738 UINT r;
739
740 TRACE("%d %d %d\n", hInstall, iRunMode, fState);
741
742 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
743 if (!package)
744 {
745 HRESULT hr;
746 IWineMsiRemotePackage *remote_package;
747
748 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
749 if (!remote_package)
750 return FALSE;
751
752 hr = IWineMsiRemotePackage_SetMode( remote_package, iRunMode, fState );
753 IWineMsiRemotePackage_Release( remote_package );
754
755 if (FAILED(hr))
756 {
757 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
758 return HRESULT_CODE(hr);
759
760 return ERROR_FUNCTION_FAILED;
761 }
762
763 return ERROR_SUCCESS;
764 }
765
766 switch (iRunMode)
767 {
768 case MSIRUNMODE_REBOOTATEND:
769 package->need_reboot = 1;
770 r = ERROR_SUCCESS;
771 break;
772
773 case MSIRUNMODE_REBOOTNOW:
774 FIXME("unimplemented run mode: %d\n", iRunMode);
775 r = ERROR_FUNCTION_FAILED;
776 break;
777
778 default:
779 r = ERROR_ACCESS_DENIED;
780 }
781
782 msiobj_release( &package->hdr );
783 return r;
784 }
785
786 /***********************************************************************
787 * MsiSetFeatureStateA (MSI.@)
788 *
789 * According to the docs, when this is called it immediately recalculates
790 * all the component states as well
791 */
792 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
793 INSTALLSTATE iState)
794 {
795 LPWSTR szwFeature = NULL;
796 UINT rc;
797
798 szwFeature = strdupAtoW(szFeature);
799
800 if (!szwFeature)
801 return ERROR_FUNCTION_FAILED;
802
803 rc = MsiSetFeatureStateW(hInstall,szwFeature, iState);
804
805 msi_free(szwFeature);
806
807 return rc;
808 }
809
810
811
812 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
813 INSTALLSTATE iState)
814 {
815 UINT rc = ERROR_SUCCESS;
816 MSIFEATURE *feature, *child;
817
818 TRACE("%s %i\n", debugstr_w(szFeature), iState);
819
820 feature = get_loaded_feature(package,szFeature);
821 if (!feature)
822 return ERROR_UNKNOWN_FEATURE;
823
824 if (iState == INSTALLSTATE_ADVERTISED &&
825 feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
826 return ERROR_FUNCTION_FAILED;
827
828 feature->ActionRequest = iState;
829
830 ACTION_UpdateComponentStates( package, feature );
831
832 /* update all the features that are children of this feature */
833 LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
834 {
835 if (child->Feature_Parent && !strcmpW( szFeature, child->Feature_Parent ))
836 MSI_SetFeatureStateW(package, child->Feature, iState);
837 }
838
839 return rc;
840 }
841
842 /***********************************************************************
843 * MsiSetFeatureStateW (MSI.@)
844 */
845 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
846 INSTALLSTATE iState)
847 {
848 MSIPACKAGE* package;
849 UINT rc = ERROR_SUCCESS;
850
851 TRACE("%s %i\n",debugstr_w(szFeature), iState);
852
853 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
854 if (!package)
855 {
856 HRESULT hr;
857 BSTR feature;
858 IWineMsiRemotePackage *remote_package;
859
860 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
861 if (!remote_package)
862 return ERROR_INVALID_HANDLE;
863
864 feature = SysAllocString(szFeature);
865 if (!feature)
866 {
867 IWineMsiRemotePackage_Release(remote_package);
868 return ERROR_OUTOFMEMORY;
869 }
870
871 hr = IWineMsiRemotePackage_SetFeatureState(remote_package, feature, iState);
872
873 SysFreeString(feature);
874 IWineMsiRemotePackage_Release(remote_package);
875
876 if (FAILED(hr))
877 {
878 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
879 return HRESULT_CODE(hr);
880
881 return ERROR_FUNCTION_FAILED;
882 }
883
884 return ERROR_SUCCESS;
885 }
886
887 rc = MSI_SetFeatureStateW(package,szFeature,iState);
888
889 msiobj_release( &package->hdr );
890 return rc;
891 }
892
893 /***********************************************************************
894 * MsiGetFeatureStateA (MSI.@)
895 */
896 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
897 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
898 {
899 LPWSTR szwFeature = NULL;
900 UINT rc;
901
902 szwFeature = strdupAtoW(szFeature);
903
904 rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
905
906 msi_free( szwFeature);
907
908 return rc;
909 }
910
911 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
912 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
913 {
914 MSIFEATURE *feature;
915
916 feature = get_loaded_feature(package,szFeature);
917 if (!feature)
918 return ERROR_UNKNOWN_FEATURE;
919
920 if (piInstalled)
921 *piInstalled = feature->Installed;
922
923 if (piAction)
924 *piAction = feature->ActionRequest;
925
926 TRACE("returning %i %i\n", feature->Installed, feature->ActionRequest);
927
928 return ERROR_SUCCESS;
929 }
930
931 /***********************************************************************
932 * MsiGetFeatureStateW (MSI.@)
933 */
934 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
935 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
936 {
937 MSIPACKAGE* package;
938 UINT ret;
939
940 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
941
942 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
943 if (!package)
944 {
945 HRESULT hr;
946 BSTR feature;
947 IWineMsiRemotePackage *remote_package;
948
949 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
950 if (!remote_package)
951 return ERROR_INVALID_HANDLE;
952
953 feature = SysAllocString(szFeature);
954 if (!feature)
955 {
956 IWineMsiRemotePackage_Release(remote_package);
957 return ERROR_OUTOFMEMORY;
958 }
959
960 hr = IWineMsiRemotePackage_GetFeatureState(remote_package, feature,
961 piInstalled, piAction);
962
963 SysFreeString(feature);
964 IWineMsiRemotePackage_Release(remote_package);
965
966 if (FAILED(hr))
967 {
968 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
969 return HRESULT_CODE(hr);
970
971 return ERROR_FUNCTION_FAILED;
972 }
973
974 return ERROR_SUCCESS;
975 }
976
977 ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
978 msiobj_release( &package->hdr );
979 return ret;
980 }
981
982 /***********************************************************************
983 * MsiGetFeatureCostA (MSI.@)
984 */
985 UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
986 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
987 {
988 LPWSTR szwFeature = NULL;
989 UINT rc;
990
991 szwFeature = strdupAtoW(szFeature);
992
993 rc = MsiGetFeatureCostW(hInstall, szwFeature, iCostTree, iState, piCost);
994
995 msi_free(szwFeature);
996
997 return rc;
998 }
999
1000 static INT feature_cost( MSIFEATURE *feature )
1001 {
1002 INT cost = 0;
1003 MSICOMPONENT *comp;
1004
1005 LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry )
1006 {
1007 cost += comp->Cost;
1008 }
1009 return cost;
1010 }
1011
1012 UINT MSI_GetFeatureCost( MSIPACKAGE *package, MSIFEATURE *feature, MSICOSTTREE tree,
1013 INSTALLSTATE state, LPINT cost )
1014 {
1015 TRACE("%s, %u, %d, %p\n", debugstr_w(feature->Feature), tree, state, cost);
1016
1017 *cost = 0;
1018 switch (tree)
1019 {
1020 case MSICOSTTREE_CHILDREN:
1021 {
1022 MSIFEATURE *child;
1023
1024 LIST_FOR_EACH_ENTRY( child, &feature->Children, MSIFEATURE, entry )
1025 {
1026 if (child->ActionRequest == state)
1027 *cost += feature_cost( child );
1028 }
1029 break;
1030 }
1031 case MSICOSTTREE_PARENTS:
1032 {
1033 const WCHAR *feature_parent = feature->Feature_Parent;
1034 for (;;)
1035 {
1036 MSIFEATURE *parent = get_loaded_feature( package, feature_parent );
1037 if (!parent)
1038 break;
1039
1040 if (parent->ActionRequest == state)
1041 *cost += feature_cost( parent );
1042
1043 feature_parent = parent->Feature_Parent;
1044 }
1045 break;
1046 }
1047 case MSICOSTTREE_SELFONLY:
1048 if (feature->ActionRequest == state)
1049 *cost = feature_cost( feature );
1050 break;
1051
1052 default:
1053 WARN("unhandled cost tree %u\n", tree);
1054 break;
1055 }
1056
1057 *cost /= 512;
1058 return ERROR_SUCCESS;
1059 }
1060
1061 /***********************************************************************
1062 * MsiGetFeatureCostW (MSI.@)
1063 */
1064 UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
1065 MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
1066 {
1067 MSIPACKAGE *package;
1068 MSIFEATURE *feature;
1069 UINT ret;
1070
1071 TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
1072 iCostTree, iState, piCost);
1073
1074 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1075 if (!package)
1076 {
1077 HRESULT hr;
1078 BSTR feature;
1079 IWineMsiRemotePackage *remote_package;
1080
1081 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1082 if (!remote_package)
1083 return ERROR_INVALID_HANDLE;
1084
1085 feature = SysAllocString(szFeature);
1086 if (!feature)
1087 {
1088 IWineMsiRemotePackage_Release(remote_package);
1089 return ERROR_OUTOFMEMORY;
1090 }
1091
1092 hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
1093 iCostTree, iState, piCost);
1094
1095 SysFreeString(feature);
1096 IWineMsiRemotePackage_Release(remote_package);
1097
1098 if (FAILED(hr))
1099 {
1100 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1101 return HRESULT_CODE(hr);
1102
1103 return ERROR_FUNCTION_FAILED;
1104 }
1105
1106 return ERROR_SUCCESS;
1107 }
1108
1109 feature = get_loaded_feature(package, szFeature);
1110
1111 if (feature)
1112 ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
1113 else
1114 ret = ERROR_UNKNOWN_FEATURE;
1115
1116 msiobj_release( &package->hdr );
1117 return ret;
1118 }
1119
1120 /***********************************************************************
1121 * MsiSetComponentStateA (MSI.@)
1122 */
1123 UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1124 INSTALLSTATE iState)
1125 {
1126 UINT rc;
1127 LPWSTR szwComponent = strdupAtoW(szComponent);
1128
1129 rc = MsiSetComponentStateW(hInstall, szwComponent, iState);
1130
1131 msi_free(szwComponent);
1132
1133 return rc;
1134 }
1135
1136 /***********************************************************************
1137 * MsiGetComponentStateA (MSI.@)
1138 */
1139 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
1140 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1141 {
1142 LPWSTR szwComponent= NULL;
1143 UINT rc;
1144
1145 szwComponent= strdupAtoW(szComponent);
1146
1147 rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
1148
1149 msi_free( szwComponent);
1150
1151 return rc;
1152 }
1153
1154 static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1155 INSTALLSTATE iState)
1156 {
1157 MSICOMPONENT *comp;
1158
1159 TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);
1160
1161 comp = get_loaded_component(package, szComponent);
1162 if (!comp)
1163 return ERROR_UNKNOWN_COMPONENT;
1164
1165 if (comp->Enabled)
1166 comp->Action = iState;
1167
1168 return ERROR_SUCCESS;
1169 }
1170
1171 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
1172 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1173 {
1174 MSICOMPONENT *comp;
1175
1176 TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
1177 piInstalled, piAction);
1178
1179 comp = get_loaded_component(package,szComponent);
1180 if (!comp)
1181 return ERROR_UNKNOWN_COMPONENT;
1182
1183 if (piInstalled)
1184 {
1185 if (comp->Enabled)
1186 *piInstalled = comp->Installed;
1187 else
1188 *piInstalled = INSTALLSTATE_UNKNOWN;
1189 }
1190
1191 if (piAction)
1192 {
1193 if (comp->Enabled)
1194 *piAction = comp->Action;
1195 else
1196 *piAction = INSTALLSTATE_UNKNOWN;
1197 }
1198
1199 TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
1200 return ERROR_SUCCESS;
1201 }
1202
1203 /***********************************************************************
1204 * MsiSetComponentStateW (MSI.@)
1205 */
1206 UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1207 INSTALLSTATE iState)
1208 {
1209 MSIPACKAGE* package;
1210 UINT ret;
1211
1212 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1213 if (!package)
1214 {
1215 HRESULT hr;
1216 BSTR component;
1217 IWineMsiRemotePackage *remote_package;
1218
1219 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1220 if (!remote_package)
1221 return ERROR_INVALID_HANDLE;
1222
1223 component = SysAllocString(szComponent);
1224 if (!component)
1225 {
1226 IWineMsiRemotePackage_Release(remote_package);
1227 return ERROR_OUTOFMEMORY;
1228 }
1229
1230 hr = IWineMsiRemotePackage_SetComponentState(remote_package, component, iState);
1231
1232 SysFreeString(component);
1233 IWineMsiRemotePackage_Release(remote_package);
1234
1235 if (FAILED(hr))
1236 {
1237 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1238 return HRESULT_CODE(hr);
1239
1240 return ERROR_FUNCTION_FAILED;
1241 }
1242
1243 return ERROR_SUCCESS;
1244 }
1245
1246 ret = MSI_SetComponentStateW(package, szComponent, iState);
1247 msiobj_release(&package->hdr);
1248 return ret;
1249 }
1250
1251 /***********************************************************************
1252 * MsiGetComponentStateW (MSI.@)
1253 */
1254 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
1255 INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
1256 {
1257 MSIPACKAGE* package;
1258 UINT ret;
1259
1260 TRACE("%d %s %p %p\n", hInstall, debugstr_w(szComponent),
1261 piInstalled, piAction);
1262
1263 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1264 if (!package)
1265 {
1266 HRESULT hr;
1267 BSTR component;
1268 IWineMsiRemotePackage *remote_package;
1269
1270 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1271 if (!remote_package)
1272 return ERROR_INVALID_HANDLE;
1273
1274 component = SysAllocString(szComponent);
1275 if (!component)
1276 {
1277 IWineMsiRemotePackage_Release(remote_package);
1278 return ERROR_OUTOFMEMORY;
1279 }
1280
1281 hr = IWineMsiRemotePackage_GetComponentState(remote_package, component,
1282 piInstalled, piAction);
1283
1284 SysFreeString(component);
1285 IWineMsiRemotePackage_Release(remote_package);
1286
1287 if (FAILED(hr))
1288 {
1289 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1290 return HRESULT_CODE(hr);
1291
1292 return ERROR_FUNCTION_FAILED;
1293 }
1294
1295 return ERROR_SUCCESS;
1296 }
1297
1298 ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
1299 msiobj_release( &package->hdr );
1300 return ret;
1301 }
1302
1303 /***********************************************************************
1304 * MsiGetLanguage (MSI.@)
1305 */
1306 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
1307 {
1308 MSIPACKAGE* package;
1309 LANGID langid;
1310 static const WCHAR szProductLanguage[] =
1311 {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
1312
1313 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1314 if (!package)
1315 {
1316 HRESULT hr;
1317 LANGID lang;
1318 IWineMsiRemotePackage *remote_package;
1319
1320 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1321 if (!remote_package)
1322 return ERROR_INVALID_HANDLE;
1323
1324 hr = IWineMsiRemotePackage_GetLanguage(remote_package, &lang);
1325
1326 if (SUCCEEDED(hr))
1327 return lang;
1328
1329 return 0;
1330 }
1331
1332 langid = msi_get_property_int( package->db, szProductLanguage, 0 );
1333 msiobj_release( &package->hdr );
1334 return langid;
1335 }
1336
1337 UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
1338 {
1339 static const WCHAR szInstallLevel[] = {
1340 'I','N','S','T','A','L','L','L','E','V','E','L',0 };
1341 static const WCHAR fmt[] = { '%','d',0 };
1342 WCHAR level[6];
1343 UINT r;
1344
1345 TRACE("%p %i\n", package, iInstallLevel);
1346
1347 if (iInstallLevel > 32767)
1348 return ERROR_INVALID_PARAMETER;
1349
1350 if (iInstallLevel < 1)
1351 return MSI_SetFeatureStates( package );
1352
1353 sprintfW( level, fmt, iInstallLevel );
1354 r = msi_set_property( package->db, szInstallLevel, level );
1355 if ( r == ERROR_SUCCESS )
1356 r = MSI_SetFeatureStates( package );
1357
1358 return r;
1359 }
1360
1361 /***********************************************************************
1362 * MsiSetInstallLevel (MSI.@)
1363 */
1364 UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
1365 {
1366 MSIPACKAGE* package;
1367 UINT r;
1368
1369 TRACE("%d %i\n", hInstall, iInstallLevel);
1370
1371 package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
1372 if (!package)
1373 {
1374 HRESULT hr;
1375 IWineMsiRemotePackage *remote_package;
1376
1377 remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
1378 if (!remote_package)
1379 return ERROR_INVALID_HANDLE;
1380
1381 hr = IWineMsiRemotePackage_SetInstallLevel(remote_package, iInstallLevel);
1382
1383 IWineMsiRemotePackage_Release(remote_package);
1384
1385 if (FAILED(hr))
1386 {
1387 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
1388 return HRESULT_CODE(hr);
1389
1390 return ERROR_FUNCTION_FAILED;
1391 }
1392
1393 return ERROR_SUCCESS;
1394 }
1395
1396 r = MSI_SetInstallLevel( package, iInstallLevel );
1397
1398 msiobj_release( &package->hdr );
1399
1400 return r;
1401 }
1402
1403 /***********************************************************************
1404 * MsiGetFeatureValidStatesW (MSI.@)
1405 */
1406 UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
1407 LPDWORD pInstallState)
1408 {
1409 if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
1410 FIXME("%d %s %p stub returning %d\n",
1411 hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);
1412
1413 return ERROR_SUCCESS;
1414 }
1415
1416 /***********************************************************************
1417 * MsiGetFeatureValidStatesA (MSI.@)
1418 */
1419 UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
1420 LPDWORD pInstallState)
1421 {
1422 UINT ret;
1423 LPWSTR szwFeature = strdupAtoW(szFeature);
1424
1425 ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);
1426
1427 msi_free(szwFeature);
1428
1429 return ret;
1430 }