1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2004 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 #define COBJMACROS
22
23 #ifdef __REACTOS__
24 #define WIN32_NO_STATUS
25 #endif
26
27 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winnls.h"
32 #ifdef __REACTOS__
33 #include <ndk/rtlfuncs.h>
34 #else
35 #include "winternl.h"
36 #endif
37 #include "shlwapi.h"
38 #include "wingdi.h"
39 #include "msi.h"
40 #include "msiquery.h"
41 #include "objidl.h"
42 #include "wincrypt.h"
43 #include "winuser.h"
44 #include "wininet.h"
45 #include "winver.h"
46 #include "urlmon.h"
47 #include "shlobj.h"
48 #include "objbase.h"
49 #include "msidefs.h"
50 #include "sddl.h"
51
52 #include "wine/debug.h"
53 #include "wine/exception.h"
54
55 #include "msipriv.h"
56 #include "winemsi_s.h"
57 #include "resource.h"
58
59 WINE_DEFAULT_DEBUG_CHANNEL(msi);
60
free_feature(MSIFEATURE * feature)61 static void free_feature( MSIFEATURE *feature )
62 {
63 struct list *item, *cursor;
64
65 LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
66 {
67 FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
68 list_remove( &fl->entry );
69 free( fl );
70 }
71
72 LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
73 {
74 ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
75 list_remove( &cl->entry );
76 free( cl );
77 }
78 free( feature->Feature );
79 free( feature->Feature_Parent );
80 free( feature->Directory );
81 free( feature->Description );
82 free( feature->Title );
83 free( feature );
84 }
85
free_folder(MSIFOLDER * folder)86 static void free_folder( MSIFOLDER *folder )
87 {
88 struct list *item, *cursor;
89
90 LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
91 {
92 FolderList *fl = LIST_ENTRY( item, FolderList, entry );
93 list_remove( &fl->entry );
94 free( fl );
95 }
96 free( folder->Parent );
97 free( folder->Directory );
98 free( folder->TargetDefault );
99 free( folder->SourceLongPath );
100 free( folder->SourceShortPath );
101 free( folder->ResolvedTarget );
102 free( folder->ResolvedSource );
103 free( folder );
104 }
105
free_extension(MSIEXTENSION * ext)106 static void free_extension( MSIEXTENSION *ext )
107 {
108 struct list *item, *cursor;
109
110 LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
111 {
112 MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
113
114 list_remove( &verb->entry );
115 free( verb->Verb );
116 free( verb->Command );
117 free( verb->Argument );
118 free( verb );
119 }
120
121 free( ext->Extension );
122 free( ext->ProgIDText );
123 free( ext );
124 }
125
free_assembly(MSIASSEMBLY * assembly)126 static void free_assembly( MSIASSEMBLY *assembly )
127 {
128 free( assembly->feature );
129 free( assembly->manifest );
130 free( assembly->application );
131 free( assembly->display_name );
132 if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir );
133 free( assembly->tempdir );
134 free( assembly );
135 }
136
msi_free_action_script(MSIPACKAGE * package,UINT script)137 void msi_free_action_script( MSIPACKAGE *package, UINT script )
138 {
139 UINT i;
140 for (i = 0; i < package->script_actions_count[script]; i++)
141 free( package->script_actions[script][i] );
142
143 free( package->script_actions[script] );
144 package->script_actions[script] = NULL;
145 package->script_actions_count[script] = 0;
146 }
147
free_package_structures(MSIPACKAGE * package)148 static void free_package_structures( MSIPACKAGE *package )
149 {
150 struct list *item, *cursor;
151 int i;
152
153 LIST_FOR_EACH_SAFE( item, cursor, &package->features )
154 {
155 MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
156 list_remove( &feature->entry );
157 free_feature( feature );
158 }
159
160 LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
161 {
162 MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
163 list_remove( &folder->entry );
164 free_folder( folder );
165 }
166
167 LIST_FOR_EACH_SAFE( item, cursor, &package->files )
168 {
169 MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
170
171 list_remove( &file->entry );
172 free( file->File );
173 free( file->FileName );
174 free( file->ShortName );
175 free( file->LongName );
176 free( file->Version );
177 free( file->Language );
178 if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
179 free( file->TargetPath );
180 free( file );
181 }
182
183 LIST_FOR_EACH_SAFE( item, cursor, &package->components )
184 {
185 MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
186
187 list_remove( &comp->entry );
188 free( comp->Component );
189 free( comp->ComponentId );
190 free( comp->Directory );
191 free( comp->Condition );
192 free( comp->KeyPath );
193 free( comp->FullKeypath );
194 if (comp->assembly) free_assembly( comp->assembly );
195 free( comp );
196 }
197
198 LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
199 {
200 MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
201
202 list_remove( &patch->entry );
203 free( patch->path );
204 free( patch );
205 }
206
207 /* clean up extension, progid, class and verb structures */
208 LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
209 {
210 MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
211
212 list_remove( &cls->entry );
213 free( cls->clsid );
214 free( cls->Context );
215 free( cls->Description );
216 free( cls->FileTypeMask );
217 free( cls->IconPath );
218 free( cls->DefInprocHandler );
219 free( cls->DefInprocHandler32 );
220 free( cls->Argument );
221 free( cls->ProgIDText );
222 free( cls );
223 }
224
225 LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
226 {
227 MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
228
229 list_remove( &ext->entry );
230 free_extension( ext );
231 }
232
233 LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
234 {
235 MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
236
237 list_remove( &progid->entry );
238 free( progid->ProgID );
239 free( progid->Description );
240 free( progid->IconPath );
241 free( progid );
242 }
243
244 LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
245 {
246 MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
247
248 list_remove( &mt->entry );
249 free( mt->suffix );
250 free( mt->clsid );
251 free( mt->ContentType );
252 free( mt );
253 }
254
255 LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
256 {
257 MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
258
259 list_remove( &appid->entry );
260 free( appid->AppID );
261 free( appid->RemoteServerName );
262 free( appid->LocalServer );
263 free( appid->ServiceParameters );
264 free( appid->DllSurrogate );
265 free( appid );
266 }
267
268 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
269 {
270 MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
271
272 list_remove( &info->entry );
273 free( info->value );
274 free( info );
275 }
276
277 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
278 {
279 MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
280
281 list_remove( &info->entry );
282 free( info->volume_label );
283 free( info->disk_prompt );
284 free( info );
285 }
286
287 for (i = 0; i < SCRIPT_MAX; i++)
288 msi_free_action_script( package, i );
289
290 for (i = 0; i < package->unique_actions_count; i++)
291 free( package->unique_actions[i] );
292 free( package->unique_actions );
293
294 LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
295 {
296 MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
297
298 list_remove( &binary->entry );
299 if (!DeleteFileW( binary->tmpfile ))
300 ERR( "failed to delete %s (%lu)\n", debugstr_w(binary->tmpfile), GetLastError() );
301 free( binary->source );
302 free( binary->tmpfile );
303 free( binary );
304 }
305
306 LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
307 {
308 MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
309
310 list_remove( &cab->entry );
311 IStorage_Release( cab->storage );
312 free( cab->stream );
313 free( cab );
314 }
315
316 LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
317 {
318 MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
319
320 list_remove( &patch->entry );
321 if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
322 {
323 ERR( "failed to delete %s (%lu)\n", debugstr_w(patch->localfile), GetLastError() );
324 }
325 msi_free_patchinfo( patch );
326 }
327
328 free( package->PackagePath );
329 free( package->ProductCode );
330 free( package->ActionFormat );
331 free( package->LastAction );
332 free( package->LastActionTemplate );
333 free( package->langids );
334
335 /* cleanup control event subscriptions */
336 msi_event_cleanup_all_subscriptions( package );
337 }
338
MSI_FreePackage(MSIOBJECTHDR * arg)339 static void MSI_FreePackage( MSIOBJECTHDR *arg)
340 {
341 MSIPACKAGE *package = (MSIPACKAGE *)arg;
342
343 msi_destroy_assembly_caches( package );
344
345 if( package->dialog )
346 msi_dialog_destroy( package->dialog );
347
348 msiobj_release( &package->db->hdr );
349 free_package_structures(package);
350 CloseHandle( package->log_file );
351 if (package->rpc_server_started)
352 RpcServerUnregisterIf(s_IWineMsiRemote_v0_0_s_ifspec, NULL, FALSE);
353 if (rpc_handle)
354 RpcBindingFree(&rpc_handle);
355 if (package->custom_server_32_process)
356 custom_stop_server(package->custom_server_32_process, package->custom_server_32_pipe);
357 if (package->custom_server_64_process)
358 custom_stop_server(package->custom_server_64_process, package->custom_server_64_pipe);
359
360 if (package->delete_on_close) DeleteFileW( package->localfile );
361 free( package->localfile );
362 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
363 }
364
create_temp_property_table(MSIPACKAGE * package)365 static UINT create_temp_property_table(MSIPACKAGE *package)
366 {
367 MSIQUERY *view;
368 UINT rc;
369
370 rc = MSI_DatabaseOpenViewW(package->db, L"CREATE TABLE `_Property` ( `_Property` CHAR(56) NOT NULL TEMPORARY, "
371 L"`Value` CHAR(98) NOT NULL TEMPORARY PRIMARY KEY `_Property`) HOLD", &view);
372 if (rc != ERROR_SUCCESS)
373 return rc;
374
375 rc = MSI_ViewExecute(view, 0);
376 MSI_ViewClose(view);
377 msiobj_release(&view->hdr);
378 return rc;
379 }
380
msi_clone_properties(MSIDATABASE * db)381 UINT msi_clone_properties( MSIDATABASE *db )
382 {
383 MSIQUERY *view_select;
384 UINT rc;
385
386 rc = MSI_DatabaseOpenViewW( db, L"SELECT * FROM `Property`", &view_select );
387 if (rc != ERROR_SUCCESS)
388 return rc;
389
390 rc = MSI_ViewExecute( view_select, 0 );
391 if (rc != ERROR_SUCCESS)
392 {
393 MSI_ViewClose( view_select );
394 msiobj_release( &view_select->hdr );
395 return rc;
396 }
397
398 while (1)
399 {
400 MSIQUERY *view_insert, *view_update;
401 MSIRECORD *rec_select;
402
403 rc = MSI_ViewFetch( view_select, &rec_select );
404 if (rc != ERROR_SUCCESS)
405 break;
406
407 rc = MSI_DatabaseOpenViewW( db, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)", &view_insert );
408 if (rc != ERROR_SUCCESS)
409 {
410 msiobj_release( &rec_select->hdr );
411 continue;
412 }
413
414 rc = MSI_ViewExecute( view_insert, rec_select );
415 MSI_ViewClose( view_insert );
416 msiobj_release( &view_insert->hdr );
417 if (rc != ERROR_SUCCESS)
418 {
419 MSIRECORD *rec_update;
420
421 TRACE("insert failed, trying update\n");
422
423 rc = MSI_DatabaseOpenViewW( db, L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = ?", &view_update );
424 if (rc != ERROR_SUCCESS)
425 {
426 WARN("open view failed %u\n", rc);
427 msiobj_release( &rec_select->hdr );
428 continue;
429 }
430
431 rec_update = MSI_CreateRecord( 2 );
432 MSI_RecordCopyField( rec_select, 1, rec_update, 2 );
433 MSI_RecordCopyField( rec_select, 2, rec_update, 1 );
434 rc = MSI_ViewExecute( view_update, rec_update );
435 if (rc != ERROR_SUCCESS)
436 WARN("update failed %u\n", rc);
437
438 MSI_ViewClose( view_update );
439 msiobj_release( &view_update->hdr );
440 msiobj_release( &rec_update->hdr );
441 }
442
443 msiobj_release( &rec_select->hdr );
444 }
445
446 MSI_ViewClose( view_select );
447 msiobj_release( &view_select->hdr );
448 return rc;
449 }
450
451 /*
452 * set_installed_prop
453 *
454 * Sets the "Installed" property to indicate that
455 * the product is installed for the current user.
456 */
set_installed_prop(MSIPACKAGE * package)457 static UINT set_installed_prop( MSIPACKAGE *package )
458 {
459 HKEY hkey;
460 UINT r;
461
462 if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
463
464 r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
465 if (r == ERROR_SUCCESS)
466 {
467 RegCloseKey( hkey );
468 msi_set_property( package->db, L"Installed", L"1", -1 );
469 }
470 return r;
471 }
472
set_user_sid_prop(MSIPACKAGE * package)473 static UINT set_user_sid_prop( MSIPACKAGE *package )
474 {
475 SID_NAME_USE use;
476 LPWSTR user_name;
477 LPWSTR sid_str = NULL, dom = NULL;
478 DWORD size, dom_size;
479 PSID psid = NULL;
480 UINT r = ERROR_FUNCTION_FAILED;
481
482 size = 0;
483 GetUserNameW( NULL, &size );
484
485 user_name = malloc( (size + 1) * sizeof(WCHAR) );
486 if (!user_name)
487 return ERROR_OUTOFMEMORY;
488
489 if (!GetUserNameW( user_name, &size ))
490 goto done;
491
492 size = 0;
493 dom_size = 0;
494 LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
495
496 psid = malloc( size );
497 dom = malloc( dom_size * sizeof (WCHAR) );
498 if (!psid || !dom)
499 {
500 r = ERROR_OUTOFMEMORY;
501 goto done;
502 }
503
504 if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
505 goto done;
506
507 if (!ConvertSidToStringSidW( psid, &sid_str ))
508 goto done;
509
510 r = msi_set_property( package->db, L"UserSID", sid_str, -1 );
511
512 done:
513 LocalFree( sid_str );
514 free( dom );
515 free( psid );
516 free( user_name );
517
518 return r;
519 }
520
get_fusion_filename(MSIPACKAGE * package)521 static LPWSTR get_fusion_filename(MSIPACKAGE *package)
522 {
523 HKEY netsetup, hkey;
524 LONG res;
525 DWORD size, len, type;
526 WCHAR windir[MAX_PATH], path[MAX_PATH], *filename = NULL;
527
528 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\NET Framework Setup\\NDP", 0, KEY_CREATE_SUB_KEY,
529 &netsetup);
530 if (res != ERROR_SUCCESS)
531 return NULL;
532
533 if (!RegCreateKeyExW(netsetup, L"v4\\Client", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
534 {
535 size = sizeof(path);
536 if (!RegQueryValueExW(hkey, L"InstallPath", NULL, &type, (BYTE *)path, &size))
537 {
538 len = lstrlenW(path) + lstrlenW(L"fusion.dll") + 2;
539 if (!(filename = malloc(len * sizeof(WCHAR)))) return NULL;
540
541 lstrcpyW(filename, path);
542 lstrcatW(filename, L"\\");
543 lstrcatW(filename, L"fusion.dll");
544 if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
545 {
546 TRACE( "found %s\n", debugstr_w(filename) );
547 RegCloseKey(hkey);
548 RegCloseKey(netsetup);
549 return filename;
550 }
551 }
552 RegCloseKey(hkey);
553 }
554
555 if (!RegCreateKeyExW(netsetup, L"v2.0.50727", 0, NULL, 0, KEY_QUERY_VALUE, NULL, &hkey, NULL))
556 {
557 RegCloseKey(hkey);
558 GetWindowsDirectoryW(windir, MAX_PATH);
559 len = lstrlenW(windir) + lstrlenW(L"Microsoft.NET\\Framework\\") + lstrlenW(L"v2.0.50727") +
560 lstrlenW(L"fusion.dll") + 3;
561 free(filename);
562 if (!(filename = malloc(len * sizeof(WCHAR)))) return NULL;
563
564 lstrcpyW(filename, windir);
565 lstrcatW(filename, L"\\");
566 lstrcatW(filename, L"Microsoft.NET\\Framework\\");
567 lstrcatW(filename, L"v2.0.50727");
568 lstrcatW(filename, L"\\");
569 lstrcatW(filename, L"fusion.dll");
570 if (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES)
571 {
572 TRACE( "found %s\n", debugstr_w(filename) );
573 RegCloseKey(netsetup);
574 return filename;
575 }
576 }
577
578 RegCloseKey(netsetup);
579 return filename;
580 }
581
582 struct lang_codepage
583 {
584 WORD wLanguage;
585 WORD wCodePage;
586 };
587
set_msi_assembly_prop(MSIPACKAGE * package)588 static void set_msi_assembly_prop(MSIPACKAGE *package)
589 {
590 UINT val_len;
591 DWORD size, handle;
592 LPVOID version = NULL;
593 WCHAR buf[MAX_PATH];
594 LPWSTR fusion, verstr;
595 struct lang_codepage *translate;
596
597 fusion = get_fusion_filename(package);
598 if (!fusion)
599 return;
600
601 size = GetFileVersionInfoSizeW(fusion, &handle);
602 if (!size)
603 goto done;
604
605 version = malloc(size);
606 if (!version)
607 goto done;
608
609 if (!GetFileVersionInfoW(fusion, handle, size, version))
610 goto done;
611
612 if (!VerQueryValueW(version, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &val_len))
613 goto done;
614
615 swprintf(buf, ARRAY_SIZE(buf), L"\\StringFileInfo\\%04x%04x\\ProductVersion", translate[0].wLanguage,
616 translate[0].wCodePage);
617
618 if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
619 goto done;
620
621 if (!val_len || !verstr)
622 goto done;
623
624 msi_set_property( package->db, L"MsiNetAssemblySupport", verstr, -1 );
625
626 done:
627 free(fusion);
628 free(version);
629 }
630
set_installer_properties(MSIPACKAGE * package)631 static VOID set_installer_properties(MSIPACKAGE *package)
632 {
633 WCHAR *ptr;
634 RTL_OSVERSIONINFOEXW OSVersion;
635 MEMORYSTATUSEX msex;
636 DWORD verval, len, type;
637 WCHAR pth[MAX_PATH], verstr[11], bufstr[22];
638 HDC dc;
639 HKEY hkey;
640 LPWSTR username, companyname;
641 SYSTEM_INFO sys_info;
642 LANGID langid;
643
644 /*
645 * Other things that probably should be set:
646 *
647 * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
648 * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
649 */
650
651 SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
652 lstrcatW(pth, L"\\");
653 msi_set_property( package->db, L"CommonAppDataFolder", pth, -1 );
654
655 SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
656 lstrcatW(pth, L"\\");
657 msi_set_property( package->db, L"FavoritesFolder", pth, -1 );
658
659 SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
660 lstrcatW(pth, L"\\");
661 msi_set_property( package->db, L"FontsFolder", pth, -1 );
662
663 SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
664 lstrcatW(pth, L"\\");
665 msi_set_property( package->db, L"SendToFolder", pth, -1 );
666
667 SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
668 lstrcatW(pth, L"\\");
669 msi_set_property( package->db, L"StartMenuFolder", pth, -1 );
670
671 SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
672 lstrcatW(pth, L"\\");
673 msi_set_property( package->db, L"StartupFolder", pth, -1 );
674
675 SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
676 lstrcatW(pth, L"\\");
677 msi_set_property( package->db, L"TemplateFolder", pth, -1 );
678
679 SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
680 lstrcatW(pth, L"\\");
681 msi_set_property( package->db, L"DesktopFolder", pth, -1 );
682
683 /* FIXME: set to AllUsers profile path if ALLUSERS is set */
684 SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
685 lstrcatW(pth, L"\\");
686 msi_set_property( package->db, L"ProgramMenuFolder", pth, -1 );
687
688 SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
689 lstrcatW(pth, L"\\");
690 msi_set_property( package->db, L"AdminToolsFolder", pth, -1 );
691
692 SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
693 lstrcatW(pth, L"\\");
694 msi_set_property( package->db, L"AppDataFolder", pth, -1 );
695
696 SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
697 lstrcatW(pth, L"\\");
698 msi_set_property( package->db, L"SystemFolder", pth, -1 );
699 msi_set_property( package->db, L"System16Folder", pth, -1 );
700
701 SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
702 lstrcatW(pth, L"\\");
703 msi_set_property( package->db, L"LocalAppDataFolder", pth, -1 );
704
705 SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
706 lstrcatW(pth, L"\\");
707 msi_set_property( package->db, L"MyPicturesFolder", pth, -1 );
708
709 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
710 lstrcatW(pth, L"\\");
711 msi_set_property( package->db, L"PersonalFolder", pth, -1 );
712
713 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
714 lstrcatW(pth, L"\\");
715 msi_set_property( package->db, L"WindowsFolder", pth, -1 );
716
717 SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
718 lstrcatW(pth, L"\\");
719 msi_set_property( package->db, L"PrintHoodFolder", pth, -1 );
720
721 SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
722 lstrcatW(pth, L"\\");
723 msi_set_property( package->db, L"NetHoodFolder", pth, -1 );
724
725 SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
726 lstrcatW(pth, L"\\");
727 msi_set_property( package->db, L"RecentFolder", pth, -1 );
728
729 /* Physical Memory is specified in MB. Using total amount. */
730 msex.dwLength = sizeof(msex);
731 GlobalMemoryStatusEx( &msex );
732 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", (int)(msex.ullTotalPhys / 1024 / 1024) );
733 msi_set_property( package->db, L"PhysicalMemory", bufstr, len );
734
735 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
736 ptr = wcschr(pth,'\\');
737 if (ptr) *(ptr + 1) = 0;
738 msi_set_property( package->db, L"WindowsVolume", pth, -1 );
739
740 len = GetTempPathW(MAX_PATH, pth);
741 msi_set_property( package->db, L"TempFolder", pth, len );
742
743 /* in a wine environment the user is always admin and privileged */
744 msi_set_property( package->db, L"AdminUser", L"1", -1 );
745 msi_set_property( package->db, L"Privileged", L"1", -1 );
746 msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
747
748 /* set the os things */
749 OSVersion.dwOSVersionInfoSize = sizeof(OSVersion);
750 RtlGetVersion((PRTL_OSVERSIONINFOW)&OSVersion);
751 verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
752 if (verval > 603)
753 {
754 verval = 603;
755 OSVersion.dwBuildNumber = 9600;
756 }
757 len = swprintf( verstr, ARRAY_SIZE(verstr), L"%u", verval );
758 switch (OSVersion.dwPlatformId)
759 {
760 case VER_PLATFORM_WIN32_WINDOWS:
761 msi_set_property( package->db, L"Version9X", verstr, len );
762 break;
763 case VER_PLATFORM_WIN32_NT:
764 msi_set_property( package->db, L"VersionNT", verstr, len );
765 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wProductType );
766 msi_set_property( package->db, L"MsiNTProductType", bufstr, len );
767 break;
768 }
769 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.dwBuildNumber );
770 msi_set_property( package->db, L"WindowsBuild", bufstr, len );
771 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", OSVersion.wServicePackMajor );
772 msi_set_property( package->db, L"ServicePackLevel", bufstr, len );
773
774 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u.%u", MSI_MAJORVERSION, MSI_MINORVERSION );
775 msi_set_property( package->db, L"VersionMsi", bufstr, len );
776 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%u", MSI_MAJORVERSION * 100 );
777 msi_set_property( package->db, L"VersionDatabase", bufstr, len );
778
779 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0,
780 KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hkey);
781
782 GetNativeSystemInfo( &sys_info );
783 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", sys_info.wProcessorLevel );
784 msi_set_property( package->db, L"Intel", bufstr, len );
785 if (sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
786 {
787 GetSystemDirectoryW( pth, MAX_PATH );
788 PathAddBackslashW( pth );
789 msi_set_property( package->db, L"SystemFolder", pth, -1 );
790
791 len = sizeof(pth);
792 RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
793 PathAddBackslashW( pth );
794 msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
795
796 len = sizeof(pth);
797 RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
798 PathAddBackslashW( pth );
799 msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
800 }
801 else if (sys_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
802 {
803 msi_set_property( package->db, L"MsiAMD64", bufstr, -1 );
804 msi_set_property( package->db, L"Msix64", bufstr, -1 );
805 msi_set_property( package->db, L"VersionNT64", verstr, -1 );
806
807 GetSystemDirectoryW( pth, MAX_PATH );
808 PathAddBackslashW( pth );
809 msi_set_property( package->db, L"System64Folder", pth, -1 );
810
811 GetSystemWow64DirectoryW( pth, MAX_PATH );
812 PathAddBackslashW( pth );
813 msi_set_property( package->db, L"SystemFolder", pth, -1 );
814
815 len = sizeof(pth);
816 RegQueryValueExW(hkey, L"ProgramFilesDir", 0, &type, (BYTE *)pth, &len);
817 PathAddBackslashW( pth );
818 msi_set_property( package->db, L"ProgramFiles64Folder", pth, -1 );
819
820 len = sizeof(pth);
821 RegQueryValueExW(hkey, L"ProgramFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
822 PathAddBackslashW( pth );
823 msi_set_property( package->db, L"ProgramFilesFolder", pth, -1 );
824
825 len = sizeof(pth);
826 RegQueryValueExW(hkey, L"CommonFilesDir", 0, &type, (BYTE *)pth, &len);
827 PathAddBackslashW( pth );
828 msi_set_property( package->db, L"CommonFiles64Folder", pth, -1 );
829
830 len = sizeof(pth);
831 RegQueryValueExW(hkey, L"CommonFilesDir (x86)", 0, &type, (BYTE *)pth, &len);
832 PathAddBackslashW( pth );
833 msi_set_property( package->db, L"CommonFilesFolder", pth, -1 );
834 }
835
836 RegCloseKey(hkey);
837
838 /* Screen properties. */
839 dc = GetDC(0);
840 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, HORZRES) );
841 msi_set_property( package->db, L"ScreenX", bufstr, len );
842 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, VERTRES) );
843 msi_set_property( package->db, L"ScreenY", bufstr, len );
844 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", GetDeviceCaps(dc, BITSPIXEL) );
845 msi_set_property( package->db, L"ColorBits", bufstr, len );
846 ReleaseDC(0, dc);
847
848 /* USERNAME and COMPANYNAME */
849 username = msi_dup_property( package->db, L"USERNAME" );
850 companyname = msi_dup_property( package->db, L"COMPANYNAME" );
851
852 if ((!username || !companyname) &&
853 RegOpenKeyW( HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey ) == ERROR_SUCCESS)
854 {
855 if (!username &&
856 (username = msi_reg_get_val_str( hkey, L"DefName" )))
857 msi_set_property( package->db, L"USERNAME", username, -1 );
858 if (!companyname &&
859 (companyname = msi_reg_get_val_str( hkey, L"DefCompany" )))
860 msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
861 CloseHandle( hkey );
862 }
863 if ((!username || !companyname) &&
864 RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
865 KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hkey ) == ERROR_SUCCESS)
866 {
867 if (!username &&
868 (username = msi_reg_get_val_str( hkey, L"RegisteredOwner" )))
869 msi_set_property( package->db, L"USERNAME", username, -1 );
870 if (!companyname &&
871 (companyname = msi_reg_get_val_str( hkey, L"RegisteredOrganization" )))
872 msi_set_property( package->db, L"COMPANYNAME", companyname, -1 );
873 CloseHandle( hkey );
874 }
875 free( username );
876 free( companyname );
877
878 if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
879 ERR("Failed to set the UserSID property\n");
880
881 set_msi_assembly_prop( package );
882
883 langid = GetUserDefaultLangID();
884 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
885 msi_set_property( package->db, L"UserLanguageID", bufstr, len );
886
887 langid = GetSystemDefaultLangID();
888 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", langid );
889 msi_set_property( package->db, L"SystemLanguageID", bufstr, len );
890
891 len = swprintf( bufstr, ARRAY_SIZE(bufstr), L"%d", MsiQueryProductStateW(package->ProductCode) );
892 msi_set_property( package->db, L"ProductState", bufstr, len );
893
894 len = 0;
895 if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
896 {
897 WCHAR *username;
898 if ((username = malloc( len * sizeof(WCHAR) )))
899 {
900 if (GetUserNameW( username, &len ))
901 msi_set_property( package->db, L"LogonUser", username, len - 1 );
902 free( username );
903 }
904 }
905 len = 0;
906 if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
907 {
908 WCHAR *computername;
909 if ((computername = malloc( len * sizeof(WCHAR) )))
910 {
911 if (GetComputerNameW( computername, &len ))
912 msi_set_property( package->db, L"ComputerName", computername, len );
913 free( computername );
914 }
915 }
916 }
917
alloc_package(void)918 static MSIPACKAGE *alloc_package( void )
919 {
920 MSIPACKAGE *package;
921
922 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
923 MSI_FreePackage );
924 if( package )
925 {
926 list_init( &package->components );
927 list_init( &package->features );
928 list_init( &package->files );
929 list_init( &package->filepatches );
930 list_init( &package->tempfiles );
931 list_init( &package->folders );
932 list_init( &package->subscriptions );
933 list_init( &package->appids );
934 list_init( &package->classes );
935 list_init( &package->mimes );
936 list_init( &package->extensions );
937 list_init( &package->progids );
938 list_init( &package->RunningActions );
939 list_init( &package->sourcelist_info );
940 list_init( &package->sourcelist_media );
941 list_init( &package->patches );
942 list_init( &package->binaries );
943 list_init( &package->cabinet_streams );
944 }
945
946 return package;
947 }
948
load_admin_properties(MSIPACKAGE * package)949 static UINT load_admin_properties(MSIPACKAGE *package)
950 {
951 BYTE *data;
952 UINT r, sz;
953
954 r = read_stream_data(package->db->storage, L"AdminProperties", FALSE, &data, &sz);
955 if (r != ERROR_SUCCESS)
956 return r;
957
958 r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
959
960 free(data);
961 return r;
962 }
963
msi_adjust_privilege_properties(MSIPACKAGE * package)964 void msi_adjust_privilege_properties( MSIPACKAGE *package )
965 {
966 /* FIXME: this should depend on the user's privileges */
967 if (msi_get_property_int( package->db, L"ALLUSERS", 0 ) == 2)
968 {
969 TRACE("resetting ALLUSERS property from 2 to 1\n");
970 msi_set_property( package->db, L"ALLUSERS", L"1", -1 );
971 }
972 msi_set_property( package->db, L"AdminUser", L"1", -1 );
973 msi_set_property( package->db, L"Privileged", L"1", -1 );
974 msi_set_property( package->db, L"MsiRunningElevated", L"1", -1 );
975 }
976
MSI_CreatePackage(MSIDATABASE * db)977 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
978 {
979 MSIPACKAGE *package;
980 WCHAR uilevel[11];
981 int len;
982 UINT r;
983
984 TRACE("%p\n", db);
985
986 package = alloc_package();
987 if (package)
988 {
989 msiobj_addref( &db->hdr );
990 package->db = db;
991
992 package->LastAction = NULL;
993 package->LastActionTemplate = NULL;
994 package->LastActionResult = MSI_NULL_INTEGER;
995 package->WordCount = 0;
996 package->PackagePath = wcsdup( db->path );
997
998 create_temp_property_table( package );
999 msi_clone_properties( package->db );
1000 msi_adjust_privilege_properties( package );
1001
1002 package->ProductCode = msi_dup_property( package->db, L"ProductCode" );
1003
1004 set_installer_properties( package );
1005
1006 package->ui_level = gUILevel;
1007 len = swprintf( uilevel, ARRAY_SIZE(uilevel), L"%u", gUILevel & INSTALLUILEVEL_MASK );
1008 msi_set_property( package->db, L"UILevel", uilevel, len );
1009
1010 r = msi_load_suminfo_properties( package );
1011 if (r != ERROR_SUCCESS)
1012 {
1013 msiobj_release( &package->hdr );
1014 return NULL;
1015 }
1016
1017 if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1018 load_admin_properties( package );
1019
1020 package->log_file = INVALID_HANDLE_VALUE;
1021 package->script = SCRIPT_NONE;
1022 }
1023 return package;
1024 }
1025
msi_download_file(LPCWSTR szUrl,LPWSTR filename)1026 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1027 {
1028 LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1029 DWORD size = 0;
1030 HRESULT hr;
1031
1032 /* call will always fail, because size is 0,
1033 * but will return ERROR_FILE_NOT_FOUND first
1034 * if the file doesn't exist
1035 */
1036 GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1037 if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1038 {
1039 cache_entry = malloc( size );
1040 if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1041 {
1042 UINT error = GetLastError();
1043 free( cache_entry );
1044 return error;
1045 }
1046
1047 lstrcpyW( filename, cache_entry->lpszLocalFileName );
1048 free( cache_entry );
1049 return ERROR_SUCCESS;
1050 }
1051
1052 hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1053 if ( FAILED(hr) )
1054 {
1055 WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1056 return ERROR_FUNCTION_FAILED;
1057 }
1058
1059 return ERROR_SUCCESS;
1060 }
1061
msi_create_empty_local_file(LPWSTR path,LPCWSTR suffix)1062 UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
1063 {
1064 DWORD time, len, i, offset;
1065 HANDLE handle;
1066
1067 time = GetTickCount();
1068 GetWindowsDirectoryW( path, MAX_PATH );
1069 lstrcatW( path, L"\\Installer\\" );
1070 CreateDirectoryW( path, NULL );
1071
1072 len = lstrlenW(path);
1073 for (i = 0; i < 0x10000; i++)
1074 {
1075 offset = swprintf( path + len, MAX_PATH - len, L"%x", (time + i) & 0xffff );
1076 memcpy( path + len + offset, suffix, (lstrlenW( suffix ) + 1) * sizeof(WCHAR) );
1077 handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1078 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1079 if (handle != INVALID_HANDLE_VALUE)
1080 {
1081 CloseHandle(handle);
1082 break;
1083 }
1084 if (GetLastError() != ERROR_FILE_EXISTS &&
1085 GetLastError() != ERROR_SHARING_VIOLATION)
1086 return ERROR_FUNCTION_FAILED;
1087 }
1088
1089 return ERROR_SUCCESS;
1090 }
1091
parse_platform(const WCHAR * str)1092 static enum platform parse_platform( const WCHAR *str )
1093 {
1094 if (!str[0] || !wcscmp( str, L"Intel" )) return PLATFORM_INTEL;
1095 else if (!wcscmp( str, L"Intel64" )) return PLATFORM_INTEL64;
1096 else if (!wcscmp( str, L"x64" ) || !wcscmp( str, L"AMD64" )) return PLATFORM_X64;
1097 else if (!wcscmp( str, L"Arm" )) return PLATFORM_ARM;
1098 else if (!wcscmp( str, L"Arm64" )) return PLATFORM_ARM64;
1099 return PLATFORM_UNRECOGNIZED;
1100 }
1101
parse_suminfo(MSISUMMARYINFO * si,MSIPACKAGE * package)1102 static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
1103 {
1104 WCHAR *template, *p, *q, *platform;
1105 DWORD i, count;
1106
1107 package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
1108 TRACE("version: %d\n", package->version);
1109
1110 template = msi_suminfo_dup_string( si, PID_TEMPLATE );
1111 if (!template)
1112 return ERROR_SUCCESS; /* native accepts missing template property */
1113
1114 TRACE("template: %s\n", debugstr_w(template));
1115
1116 p = wcschr( template, ';' );
1117 if (!p)
1118 {
1119 WARN("invalid template string %s\n", debugstr_w(template));
1120 free( template );
1121 return ERROR_PATCH_PACKAGE_INVALID;
1122 }
1123 *p = 0;
1124 platform = template;
1125 if ((q = wcschr( platform, ',' ))) *q = 0;
1126 package->platform = parse_platform( platform );
1127 while (package->platform == PLATFORM_UNRECOGNIZED && q)
1128 {
1129 platform = q + 1;
1130 if ((q = wcschr( platform, ',' ))) *q = 0;
1131 package->platform = parse_platform( platform );
1132 }
1133 if (package->platform == PLATFORM_UNRECOGNIZED)
1134 {
1135 WARN("unknown platform %s\n", debugstr_w(template));
1136 free( template );
1137 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1138 }
1139 p++;
1140 if (!*p)
1141 {
1142 free( template );
1143 return ERROR_SUCCESS;
1144 }
1145 count = 1;
1146 for (q = p; (q = wcschr( q, ',' )); q++) count++;
1147
1148 package->langids = malloc( count * sizeof(LANGID) );
1149 if (!package->langids)
1150 {
1151 free( template );
1152 return ERROR_OUTOFMEMORY;
1153 }
1154
1155 i = 0;
1156 while (*p)
1157 {
1158 q = wcschr( p, ',' );
1159 if (q) *q = 0;
1160 package->langids[i] = wcstol( p, NULL, 10 );
1161 if (!q) break;
1162 p = q + 1;
1163 i++;
1164 }
1165 package->num_langids = i + 1;
1166
1167 free( template );
1168 return ERROR_SUCCESS;
1169 }
1170
validate_package(MSIPACKAGE * package)1171 static UINT validate_package( MSIPACKAGE *package )
1172 {
1173 UINT i;
1174
1175 if (package->platform == PLATFORM_INTEL64)
1176 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1177 #ifndef __arm__
1178 if (package->platform == PLATFORM_ARM)
1179 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1180 #endif
1181 #ifndef __aarch64__
1182 if (package->platform == PLATFORM_ARM64)
1183 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1184 #endif
1185 if (package->platform == PLATFORM_X64)
1186 {
1187 if (!is_64bit && !is_wow64)
1188 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1189 if (package->version < 200)
1190 return ERROR_INSTALL_PACKAGE_INVALID;
1191 }
1192 if (!package->num_langids)
1193 {
1194 return ERROR_SUCCESS;
1195 }
1196 for (i = 0; i < package->num_langids; i++)
1197 {
1198 LANGID langid = package->langids[i];
1199
1200 if (PRIMARYLANGID( langid ) == LANG_NEUTRAL)
1201 {
1202 langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) );
1203 }
1204 if (SUBLANGID( langid ) == SUBLANG_NEUTRAL)
1205 {
1206 langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) );
1207 }
1208 if (IsValidLocale( langid, LCID_INSTALLED ))
1209 return ERROR_SUCCESS;
1210 }
1211 return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
1212 }
1213
get_property(MSIDATABASE * db,const WCHAR * prop)1214 static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop )
1215 {
1216 WCHAR query[MAX_PATH];
1217 MSIQUERY *view;
1218 MSIRECORD *rec;
1219 WCHAR *ret = NULL;
1220
1221 swprintf(query, ARRAY_SIZE(query), L"SELECT `Value` FROM `Property` WHERE `Property`='%s'", prop);
1222 if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
1223 {
1224 return NULL;
1225 }
1226 if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
1227 {
1228 MSI_ViewClose( view );
1229 msiobj_release( &view->hdr );
1230 return NULL;
1231 }
1232 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
1233 {
1234 ret = wcsdup( MSI_RecordGetString( rec, 1 ) );
1235 msiobj_release( &rec->hdr );
1236 }
1237 MSI_ViewClose( view );
1238 msiobj_release( &view->hdr );
1239 return ret;
1240 }
1241
get_product_code(MSIDATABASE * db)1242 static WCHAR *get_product_code( MSIDATABASE *db )
1243 {
1244 return get_property( db, L"ProductCode" );
1245 }
1246
get_product_version(MSIDATABASE * db)1247 static WCHAR *get_product_version( MSIDATABASE *db )
1248 {
1249 return get_property( db, L"ProductVersion" );
1250 }
1251
get_registered_local_package(const WCHAR * product,WCHAR * localfile)1252 static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile )
1253 {
1254 MSIINSTALLCONTEXT context;
1255 WCHAR *filename;
1256 HKEY props_key;
1257 UINT r;
1258
1259 r = msi_locate_product( product, &context );
1260 if (r != ERROR_SUCCESS)
1261 return r;
1262
1263 r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
1264 if (r != ERROR_SUCCESS)
1265 return r;
1266
1267 filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
1268 RegCloseKey( props_key );
1269 if (!filename)
1270 return ERROR_FUNCTION_FAILED;
1271
1272 lstrcpyW( localfile, filename );
1273 free( filename );
1274 return ERROR_SUCCESS;
1275 }
1276
msi_get_package_code(MSIDATABASE * db)1277 WCHAR *msi_get_package_code( MSIDATABASE *db )
1278 {
1279 WCHAR *ret;
1280 MSISUMMARYINFO *si;
1281 UINT r;
1282
1283 r = msi_get_suminfo( db->storage, 0, &si );
1284 if (r != ERROR_SUCCESS)
1285 {
1286 r = msi_get_db_suminfo( db, 0, &si );
1287 if (r != ERROR_SUCCESS)
1288 {
1289 WARN("failed to load summary info %u\n", r);
1290 return NULL;
1291 }
1292 }
1293 ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
1294 msiobj_release( &si->hdr );
1295 return ret;
1296 }
1297
get_local_package(MSIDATABASE * db,WCHAR * localfile)1298 static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile )
1299 {
1300 WCHAR *product_code;
1301 UINT r;
1302
1303 if (!(product_code = get_product_code( db )))
1304 return ERROR_INSTALL_PACKAGE_INVALID;
1305 r = get_registered_local_package( product_code, localfile );
1306 free( product_code );
1307 return r;
1308 }
1309
msi_set_original_database_property(MSIDATABASE * db,const WCHAR * package)1310 UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package )
1311 {
1312 UINT r;
1313
1314 if (UrlIsW( package, URLIS_URL ))
1315 r = msi_set_property( db, L"OriginalDatabase", package, -1 );
1316 else if (package[0] == '#')
1317 r = msi_set_property( db, L"OriginalDatabase", db->path, -1 );
1318 else
1319 {
1320 DWORD len;
1321 WCHAR *path;
1322
1323 if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError();
1324 if (!(path = malloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
1325 len = GetFullPathNameW( package, len, path, NULL );
1326 r = msi_set_property( db, L"OriginalDatabase", path, len );
1327 free( path );
1328 }
1329 return r;
1330 }
1331
1332 #ifdef __REACTOS__
1333 BOOL WINAPI ApphelpCheckRunAppEx(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PCWSTR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason, PVOID *SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize,
1334 PVOID *SxsData, PULONG SxsDataSize, PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
1335 BOOL WINAPI SE_DynamicShim(LPCWSTR ProcessImage, PVOID hsdb, PVOID pQueryResult, LPCSTR Module, LPDWORD lpdwDynamicToken);
1336 PVOID WINAPI SdbInitDatabase(DWORD flags, LPCWSTR path);
1337 PVOID WINAPI SdbReleaseDatabase(PVOID hsdb);
1338
1339 #define HID_DOS_PATHS 0x1
1340 #define SDB_DATABASE_MAIN_SHIM 0x80030000
1341
1342 #define APPHELP_VALID_RESULT 0x10000
1343 #define APPHELP_RESULT_FOUND 0x40000
1344
1345 static void
AppHelpCheckPackage(LPCWSTR szPackage)1346 AppHelpCheckPackage(LPCWSTR szPackage)
1347 {
1348 USHORT ExeType = 0;
1349 ULONG Reason = 0;
1350
1351 PVOID QueryResult = NULL;
1352 ULONG QueryResultSize = 0;
1353
1354 HANDLE Handle = NULL;
1355 BOOL Continue = ApphelpCheckRunAppEx(
1356 Handle, NULL, NULL, szPackage, NULL, ExeType, &Reason, &QueryResult, &QueryResultSize, NULL,
1357 NULL, NULL, NULL, NULL);
1358
1359 if (Continue)
1360 {
1361 if ((Reason & (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT | APPHELP_RESULT_FOUND))
1362 {
1363 DWORD dwToken;
1364 PVOID hsdb = SdbInitDatabase(HID_DOS_PATHS | SDB_DATABASE_MAIN_SHIM, NULL);
1365 if (hsdb)
1366 {
1367 BOOL bShim = SE_DynamicShim(szPackage, hsdb, QueryResult, "msi.dll", &dwToken);
1368 ERR("ReactOS HACK(CORE-13283): Used SE_DynamicShim %d!\n", bShim);
1369
1370 SdbReleaseDatabase(hsdb);
1371 }
1372 else
1373 {
1374 ERR("Unable to open SDB_DATABASE_MAIN_SHIM\n");
1375 }
1376 }
1377 }
1378
1379 if (QueryResult)
1380 RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult);
1381 }
1382 #endif
1383
MSI_OpenPackageW(LPCWSTR szPackage,DWORD dwOptions,MSIPACKAGE ** pPackage)1384 UINT MSI_OpenPackageW(LPCWSTR szPackage, DWORD dwOptions, MSIPACKAGE **pPackage)
1385 {
1386 MSIDATABASE *db;
1387 MSIPACKAGE *package;
1388 MSIHANDLE handle;
1389 MSIRECORD *data_row, *info_row;
1390 UINT r;
1391 WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
1392 LPCWSTR file = szPackage;
1393 DWORD index = 0;
1394 MSISUMMARYINFO *si;
1395 BOOL delete_on_close = FALSE;
1396 WCHAR *info_template, *productname, *product_code;
1397 MSIINSTALLCONTEXT context;
1398
1399 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1400
1401 MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
1402
1403 localfile[0] = 0;
1404 if( szPackage[0] == '#' )
1405 {
1406 handle = wcstol(&szPackage[1], NULL, 10);
1407 if (!(db = msihandle2msiinfo(handle, MSIHANDLETYPE_DATABASE)))
1408 return ERROR_INVALID_HANDLE;
1409 }
1410 else
1411 {
1412 WCHAR *product_version = NULL;
1413
1414 if ( UrlIsW( szPackage, URLIS_URL ) )
1415 {
1416 r = msi_download_file( szPackage, cachefile );
1417 if (r != ERROR_SUCCESS)
1418 return r;
1419
1420 file = cachefile;
1421 }
1422 #ifdef __REACTOS__
1423 AppHelpCheckPackage(file);
1424 #endif
1425
1426 r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db );
1427 if (r != ERROR_SUCCESS)
1428 {
1429 if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES)
1430 return ERROR_FILE_NOT_FOUND;
1431 return r;
1432 }
1433 r = get_local_package( db, localfile );
1434 if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
1435 {
1436 DWORD localfile_attr;
1437
1438 r = msi_create_empty_local_file( localfile, L".msi" );
1439 if (r != ERROR_SUCCESS)
1440 {
1441 msiobj_release( &db->hdr );
1442 return r;
1443 }
1444
1445 if (!CopyFileW( file, localfile, FALSE ))
1446 {
1447 r = GetLastError();
1448 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
1449 DeleteFileW( localfile );
1450 msiobj_release( &db->hdr );
1451 return r;
1452 }
1453 delete_on_close = TRUE;
1454
1455 /* Remove read-only bit, we are opening it with write access in MSI_OpenDatabaseW below. */
1456 localfile_attr = GetFileAttributesW( localfile );
1457 if (localfile_attr & FILE_ATTRIBUTE_READONLY)
1458 SetFileAttributesW( localfile, localfile_attr & ~FILE_ATTRIBUTE_READONLY);
1459 }
1460 else if (dwOptions & WINE_OPENPACKAGEFLAGS_RECACHE)
1461 {
1462 if (!CopyFileW( file, localfile, FALSE ))
1463 {
1464 r = GetLastError();
1465 WARN("unable to update cached package (%u)\n", r);
1466 msiobj_release( &db->hdr );
1467 return r;
1468 }
1469 }
1470 else
1471 product_version = get_product_version( db );
1472 msiobj_release( &db->hdr );
1473 TRACE("opening package %s\n", debugstr_w( localfile ));
1474 r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
1475 if (r != ERROR_SUCCESS)
1476 {
1477 free( product_version );
1478 return r;
1479 }
1480
1481 if (product_version)
1482 {
1483 WCHAR *cache_version = get_product_version( db );
1484 if (!product_version != !cache_version ||
1485 (product_version && wcscmp(product_version, cache_version)))
1486 {
1487 msiobj_release( &db->hdr );
1488 free( product_version );
1489 free( cache_version );
1490 return ERROR_PRODUCT_VERSION;
1491 }
1492 free( product_version );
1493 free( cache_version );
1494 }
1495 }
1496 package = MSI_CreatePackage( db );
1497 msiobj_release( &db->hdr );
1498 if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
1499 package->localfile = wcsdup( localfile );
1500 package->delete_on_close = delete_on_close;
1501
1502 r = msi_get_suminfo( db->storage, 0, &si );
1503 if (r != ERROR_SUCCESS)
1504 {
1505 r = msi_get_db_suminfo( db, 0, &si );
1506 if (r != ERROR_SUCCESS)
1507 {
1508 WARN("failed to load summary info\n");
1509 msiobj_release( &package->hdr );
1510 return ERROR_INSTALL_PACKAGE_INVALID;
1511 }
1512 }
1513 r = parse_suminfo( si, package );
1514 msiobj_release( &si->hdr );
1515 if (r != ERROR_SUCCESS)
1516 {
1517 WARN("failed to parse summary info %u\n", r);
1518 msiobj_release( &package->hdr );
1519 return r;
1520 }
1521 r = validate_package( package );
1522 if (r != ERROR_SUCCESS)
1523 {
1524 msiobj_release( &package->hdr );
1525 return r;
1526 }
1527 msi_set_property( package->db, L"DATABASE", db->path, -1 );
1528 set_installed_prop( package );
1529 msi_set_context( package );
1530
1531 product_code = get_product_code( db );
1532 if (msi_locate_product( product_code, &context ) == ERROR_SUCCESS)
1533 {
1534 TRACE("product already registered\n");
1535 msi_set_property( package->db, L"ProductToBeRegistered", L"1", -1 );
1536 }
1537 free( product_code );
1538
1539 while (1)
1540 {
1541 WCHAR patch_code[GUID_SIZE];
1542 r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
1543 MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
1544 if (r != ERROR_SUCCESS)
1545 break;
1546
1547 TRACE("found registered patch %s\n", debugstr_w(patch_code));
1548
1549 r = msi_apply_registered_patch( package, patch_code );
1550 if (r != ERROR_SUCCESS)
1551 {
1552 ERR("registered patch failed to apply %u\n", r);
1553 msiobj_release( &package->hdr );
1554 return r;
1555 }
1556 index++;
1557 }
1558 if (index) msi_adjust_privilege_properties( package );
1559
1560 r = msi_set_original_database_property( package->db, szPackage );
1561 if (r != ERROR_SUCCESS)
1562 {
1563 msiobj_release( &package->hdr );
1564 return r;
1565 }
1566 if (gszLogFile)
1567 package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1568 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
1569
1570 /* FIXME: when should these messages be sent? */
1571 data_row = MSI_CreateRecord(3);
1572 if (!data_row)
1573 return ERROR_OUTOFMEMORY;
1574 MSI_RecordSetStringW(data_row, 0, NULL);
1575 MSI_RecordSetInteger(data_row, 1, 0);
1576 MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
1577 MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
1578 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
1579
1580 info_row = MSI_CreateRecord(0);
1581 if (!info_row)
1582 {
1583 msiobj_release(&data_row->hdr);
1584 return ERROR_OUTOFMEMORY;
1585 }
1586 info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
1587 MSI_RecordSetStringW(info_row, 0, info_template);
1588 free(info_template);
1589 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
1590
1591 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
1592
1593 productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
1594 MSI_RecordSetInteger(data_row, 1, 1);
1595 MSI_RecordSetStringW(data_row, 2, productname);
1596 MSI_RecordSetStringW(data_row, 3, NULL);
1597 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
1598
1599 free(productname);
1600 msiobj_release(&info_row->hdr);
1601 msiobj_release(&data_row->hdr);
1602
1603 *pPackage = package;
1604 return ERROR_SUCCESS;
1605 }
1606
MsiOpenPackageExW(const WCHAR * szPackage,DWORD dwOptions,MSIHANDLE * phPackage)1607 UINT WINAPI MsiOpenPackageExW( const WCHAR *szPackage, DWORD dwOptions, MSIHANDLE *phPackage )
1608 {
1609 MSIPACKAGE *package = NULL;
1610 UINT ret;
1611
1612 TRACE( "%s, %#lx, %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1613
1614 if( !szPackage || !phPackage )
1615 return ERROR_INVALID_PARAMETER;
1616
1617 if ( !*szPackage )
1618 {
1619 FIXME("Should create an empty database and package\n");
1620 return ERROR_FUNCTION_FAILED;
1621 }
1622
1623 if( dwOptions )
1624 FIXME( "dwOptions %#lx not supported\n", dwOptions );
1625
1626 ret = MSI_OpenPackageW( szPackage, 0, &package );
1627 if( ret == ERROR_SUCCESS )
1628 {
1629 *phPackage = alloc_msihandle( &package->hdr );
1630 if (! *phPackage)
1631 ret = ERROR_NOT_ENOUGH_MEMORY;
1632 msiobj_release( &package->hdr );
1633 }
1634 else
1635 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
1636
1637 return ret;
1638 }
1639
MsiOpenPackageW(LPCWSTR szPackage,MSIHANDLE * phPackage)1640 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1641 {
1642 return MsiOpenPackageExW( szPackage, 0, phPackage );
1643 }
1644
MsiOpenPackageExA(LPCSTR szPackage,DWORD dwOptions,MSIHANDLE * phPackage)1645 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1646 {
1647 LPWSTR szwPack = NULL;
1648 UINT ret;
1649
1650 if( szPackage )
1651 {
1652 szwPack = strdupAtoW( szPackage );
1653 if( !szwPack )
1654 return ERROR_OUTOFMEMORY;
1655 }
1656
1657 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1658
1659 free( szwPack );
1660
1661 return ret;
1662 }
1663
MsiOpenPackageA(LPCSTR szPackage,MSIHANDLE * phPackage)1664 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1665 {
1666 return MsiOpenPackageExA( szPackage, 0, phPackage );
1667 }
1668
MsiGetActiveDatabase(MSIHANDLE hInstall)1669 MSIHANDLE WINAPI MsiGetActiveDatabase( MSIHANDLE hInstall )
1670 {
1671 MSIPACKAGE *package;
1672 MSIHANDLE handle = 0;
1673 MSIHANDLE remote;
1674
1675 TRACE( "%lu\n", hInstall );
1676
1677 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1678 if( package)
1679 {
1680 handle = alloc_msihandle( &package->db->hdr );
1681 msiobj_release( &package->hdr );
1682 }
1683 else if ((remote = msi_get_remote(hInstall)))
1684 {
1685 __TRY
1686 {
1687 handle = remote_GetActiveDatabase(remote);
1688 handle = alloc_msi_remote_handle(handle);
1689 }
1690 __EXCEPT(rpc_filter)
1691 {
1692 handle = 0;
1693 }
1694 __ENDTRY
1695 }
1696
1697 return handle;
1698 }
1699
internal_ui_handler(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record,LPCWSTR message)1700 static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
1701 {
1702 if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
1703 return 0;
1704
1705 /* todo: check if message needs additional styles (topmost/foreground/modality?) */
1706
1707 switch (eMessageType & 0xff000000)
1708 {
1709 case INSTALLMESSAGE_FATALEXIT:
1710 case INSTALLMESSAGE_ERROR:
1711 case INSTALLMESSAGE_OUTOFDISKSPACE:
1712 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1713 if (!(eMessageType & MB_ICONMASK))
1714 eMessageType |= MB_ICONEXCLAMATION;
1715 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
1716 case INSTALLMESSAGE_WARNING:
1717 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1718 if (!(eMessageType & MB_ICONMASK))
1719 eMessageType |= MB_ICONASTERISK;
1720 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
1721 case INSTALLMESSAGE_USER:
1722 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1723 if (!(eMessageType & MB_ICONMASK))
1724 eMessageType |= MB_USERICON;
1725 return MessageBoxW(gUIhwnd, message, L"Windows Installer", eMessageType & 0x00ffffff);
1726 case INSTALLMESSAGE_INFO:
1727 case INSTALLMESSAGE_INITIALIZE:
1728 case INSTALLMESSAGE_TERMINATE:
1729 case INSTALLMESSAGE_INSTALLSTART:
1730 case INSTALLMESSAGE_INSTALLEND:
1731 return 0;
1732 case INSTALLMESSAGE_SHOWDIALOG:
1733 {
1734 LPWSTR dialog = msi_dup_record_field(record, 0);
1735 INT rc = ACTION_DialogBox(package, dialog);
1736 free(dialog);
1737 return rc;
1738 }
1739 case INSTALLMESSAGE_ACTIONSTART:
1740 {
1741 LPWSTR deformatted;
1742 MSIRECORD *uirow = MSI_CreateRecord(1);
1743 if (!uirow) return -1;
1744 deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
1745 MSI_RecordSetStringW(uirow, 1, deformatted);
1746 msi_event_fire(package, L"ActionText", uirow);
1747
1748 free(deformatted);
1749 msiobj_release(&uirow->hdr);
1750 return 1;
1751 }
1752 case INSTALLMESSAGE_ACTIONDATA:
1753 {
1754 MSIRECORD *uirow = MSI_CreateRecord(1);
1755 if (!uirow) return -1;
1756 MSI_RecordSetStringW(uirow, 1, message);
1757 msi_event_fire(package, L"ActionData", uirow);
1758 msiobj_release(&uirow->hdr);
1759
1760 if (package->action_progress_increment)
1761 {
1762 uirow = MSI_CreateRecord(2);
1763 if (!uirow) return -1;
1764 MSI_RecordSetInteger(uirow, 1, 2);
1765 MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
1766 msi_event_fire(package, L"SetProgress", uirow);
1767 msiobj_release(&uirow->hdr);
1768 }
1769 return 1;
1770 }
1771 case INSTALLMESSAGE_PROGRESS:
1772 msi_event_fire(package, L"SetProgress", record);
1773 return 1;
1774 case INSTALLMESSAGE_COMMONDATA:
1775 switch (MSI_RecordGetInteger(record, 1))
1776 {
1777 case 0:
1778 case 1:
1779 /* do nothing */
1780 return 0;
1781 default:
1782 /* fall through */
1783 ;
1784 }
1785 default:
1786 FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
1787 return 0;
1788 }
1789 }
1790
1791 static const struct
1792 {
1793 int id;
1794 const WCHAR *text;
1795 }
1796 internal_errors[] =
1797 {
1798 {2726, L"DEBUG: Error [1]: Action not found: [2]"},
1799 {0}
1800 };
1801
get_internal_error_message(int error)1802 static LPCWSTR get_internal_error_message(int error)
1803 {
1804 int i = 0;
1805
1806 while (internal_errors[i].id != 0)
1807 {
1808 if (internal_errors[i].id == error)
1809 return internal_errors[i].text;
1810 i++;
1811 }
1812
1813 FIXME("missing error message %d\n", error);
1814 return NULL;
1815 }
1816
1817 /* Returned string must be freed */
msi_get_error_message(MSIDATABASE * db,int error)1818 LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
1819 {
1820 MSIRECORD *record;
1821 LPWSTR ret = NULL;
1822
1823 if ((record = MSI_QueryGetRecord(db, L"SELECT `Message` FROM `Error` WHERE `Error` = %d", error)))
1824 {
1825 ret = msi_dup_record_field(record, 1);
1826 msiobj_release(&record->hdr);
1827 }
1828 else if (error < 2000)
1829 {
1830 int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
1831 if (len)
1832 {
1833 ret = malloc((len + 1) * sizeof(WCHAR));
1834 LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
1835 }
1836 else
1837 ret = NULL;
1838 }
1839
1840 return ret;
1841 }
1842
MSI_ProcessMessageVerbatim(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record)1843 INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
1844 {
1845 LPWSTR message = {0};
1846 DWORD len;
1847 DWORD log_type = 1 << (eMessageType >> 24);
1848 UINT res;
1849 INT rc = 0;
1850 char *msg;
1851
1852 TRACE("%x\n", eMessageType);
1853 if (TRACE_ON(msi)) dump_record(record);
1854
1855 if (!package || !record)
1856 message = NULL;
1857 else {
1858 res = MSI_FormatRecordW(package, record, message, &len);
1859 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
1860 return res;
1861 len++;
1862 message = malloc(len * sizeof(WCHAR));
1863 if (!message) return ERROR_OUTOFMEMORY;
1864 MSI_FormatRecordW(package, record, message, &len);
1865 }
1866
1867 /* convert it to ANSI */
1868 len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1869 msg = malloc( len );
1870 WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1871
1872 if (gUIHandlerRecord && (gUIFilterRecord & log_type))
1873 {
1874 MSIHANDLE rec = alloc_msihandle(&record->hdr);
1875 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, hRecord = %lu)\n",
1876 gUIHandlerRecord, gUIContextRecord, eMessageType, rec );
1877 rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
1878 MsiCloseHandle( rec );
1879 }
1880 if (!rc && gUIHandlerW && (gUIFilter & log_type))
1881 {
1882 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
1883 gUIHandlerW, gUIContext, eMessageType, debugstr_w(message) );
1884 rc = gUIHandlerW( gUIContext, eMessageType, message );
1885 }
1886 else if (!rc && gUIHandlerA && (gUIFilter & log_type))
1887 {
1888 TRACE( "calling UI handler %p(pvContext = %p, iMessageType = %#x, szMessage = %s)\n",
1889 gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg) );
1890 rc = gUIHandlerA( gUIContext, eMessageType, msg );
1891 }
1892
1893 if (!rc)
1894 rc = internal_ui_handler(package, eMessageType, record, message);
1895
1896 if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
1897 (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
1898 {
1899 DWORD written;
1900 WriteFile( package->log_file, msg, len - 1, &written, NULL );
1901 WriteFile( package->log_file, "\n", 1, &written, NULL );
1902 }
1903 free( msg );
1904 free( message );
1905
1906 return rc;
1907 }
1908
MSI_ProcessMessage(MSIPACKAGE * package,INSTALLMESSAGE eMessageType,MSIRECORD * record)1909 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
1910 {
1911 switch (eMessageType & 0xff000000)
1912 {
1913 case INSTALLMESSAGE_FATALEXIT:
1914 case INSTALLMESSAGE_ERROR:
1915 case INSTALLMESSAGE_WARNING:
1916 case INSTALLMESSAGE_USER:
1917 case INSTALLMESSAGE_INFO:
1918 case INSTALLMESSAGE_OUTOFDISKSPACE:
1919 if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
1920 {
1921 /* error message */
1922
1923 LPWSTR template;
1924 LPWSTR template_rec = NULL, template_prefix = NULL;
1925 int error = MSI_RecordGetInteger(record, 1);
1926
1927 if (MSI_RecordIsNull(record, 0))
1928 {
1929 if (error >= 32)
1930 {
1931 template_rec = msi_get_error_message(package->db, error);
1932
1933 if (!template_rec && error >= 2000)
1934 {
1935 /* internal error, not localized */
1936 if ((template_rec = (LPWSTR) get_internal_error_message(error)))
1937 {
1938 MSI_RecordSetStringW(record, 0, template_rec);
1939 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
1940 }
1941 template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
1942 MSI_RecordSetStringW(record, 0, template_rec);
1943 MSI_ProcessMessageVerbatim(package, eMessageType, record);
1944 free(template_rec);
1945 return 0;
1946 }
1947 }
1948 }
1949 else
1950 template_rec = msi_dup_record_field(record, 0);
1951
1952 template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
1953 if (!template_prefix) template_prefix = wcsdup(L"");
1954
1955 if (!template_rec)
1956 {
1957 /* always returns 0 */
1958 MSI_RecordSetStringW(record, 0, template_prefix);
1959 MSI_ProcessMessageVerbatim(package, eMessageType, record);
1960 free(template_prefix);
1961 return 0;
1962 }
1963
1964 template = malloc((wcslen(template_rec) + wcslen(template_prefix) + 1) * sizeof(WCHAR));
1965 if (!template)
1966 {
1967 free(template_prefix);
1968 free(template_rec);
1969 return ERROR_OUTOFMEMORY;
1970 }
1971
1972 lstrcpyW(template, template_prefix);
1973 lstrcatW(template, template_rec);
1974 MSI_RecordSetStringW(record, 0, template);
1975
1976 free(template_prefix);
1977 free(template_rec);
1978 free(template);
1979 }
1980 break;
1981 case INSTALLMESSAGE_ACTIONSTART:
1982 {
1983 WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
1984 MSI_RecordSetStringW(record, 0, template);
1985 free(template);
1986
1987 free(package->LastAction);
1988 free(package->LastActionTemplate);
1989 package->LastAction = msi_dup_record_field(record, 1);
1990 if (!package->LastAction) package->LastAction = wcsdup(L"");
1991 package->LastActionTemplate = msi_dup_record_field(record, 3);
1992 break;
1993 }
1994 case INSTALLMESSAGE_ACTIONDATA:
1995 if (package->LastAction && package->LastActionTemplate)
1996 {
1997 size_t len = lstrlenW(package->LastAction) + lstrlenW(package->LastActionTemplate) + 7;
1998 WCHAR *template = malloc(len * sizeof(WCHAR));
1999 if (!template) return ERROR_OUTOFMEMORY;
2000 swprintf(template, len, L"{{%s: }}%s", package->LastAction, package->LastActionTemplate);
2001 MSI_RecordSetStringW(record, 0, template);
2002 free(template);
2003 }
2004 break;
2005 case INSTALLMESSAGE_COMMONDATA:
2006 {
2007 WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA);
2008 MSI_RecordSetStringW(record, 0, template);
2009 free(template);
2010 }
2011 break;
2012 }
2013
2014 return MSI_ProcessMessageVerbatim(package, eMessageType, record);
2015 }
2016
MsiProcessMessage(MSIHANDLE hInstall,INSTALLMESSAGE eMessageType,MSIHANDLE hRecord)2017 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
2018 MSIHANDLE hRecord)
2019 {
2020 UINT ret = ERROR_INVALID_HANDLE;
2021 MSIPACKAGE *package = NULL;
2022 MSIRECORD *record = NULL;
2023
2024 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE ||
2025 (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
2026 return -1;
2027
2028 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA &&
2029 MsiRecordGetInteger(hRecord, 1) != 2)
2030 return -1;
2031
2032 record = msihandle2msiinfo(hRecord, MSIHANDLETYPE_RECORD);
2033 if (!record)
2034 return ERROR_INVALID_HANDLE;
2035
2036 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
2037 if( !package )
2038 {
2039 MSIHANDLE remote;
2040
2041 if (!(remote = msi_get_remote(hInstall)))
2042 return ERROR_INVALID_HANDLE;
2043
2044 __TRY
2045 {
2046 ret = remote_ProcessMessage(remote, eMessageType, (struct wire_record *)&record->count);
2047 }
2048 __EXCEPT(rpc_filter)
2049 {
2050 ret = GetExceptionCode();
2051 }
2052 __ENDTRY
2053
2054 msiobj_release(&record->hdr);
2055 return ret;
2056 }
2057
2058 ret = MSI_ProcessMessage( package, eMessageType, record );
2059
2060 msiobj_release( &record->hdr );
2061 msiobj_release( &package->hdr );
2062 return ret;
2063 }
2064
2065 /* property code */
2066
MsiSetPropertyA(MSIHANDLE hInstall,LPCSTR szName,LPCSTR szValue)2067 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
2068 {
2069 LPWSTR szwName = NULL, szwValue = NULL;
2070 UINT r = ERROR_OUTOFMEMORY;
2071
2072 szwName = strdupAtoW( szName );
2073 if( szName && !szwName )
2074 goto end;
2075
2076 szwValue = strdupAtoW( szValue );
2077 if( szValue && !szwValue )
2078 goto end;
2079
2080 r = MsiSetPropertyW( hInstall, szwName, szwValue);
2081
2082 end:
2083 free( szwName );
2084 free( szwValue );
2085
2086 return r;
2087 }
2088
msi_reset_source_folders(MSIPACKAGE * package)2089 void msi_reset_source_folders( MSIPACKAGE *package )
2090 {
2091 MSIFOLDER *folder;
2092
2093 LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
2094 {
2095 free( folder->ResolvedSource );
2096 folder->ResolvedSource = NULL;
2097 }
2098 }
2099
msi_set_property(MSIDATABASE * db,const WCHAR * name,const WCHAR * value,int len)2100 UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
2101 {
2102 MSIQUERY *view;
2103 MSIRECORD *row = NULL;
2104 DWORD sz = 0;
2105 WCHAR query[1024];
2106 UINT rc;
2107
2108 TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len);
2109
2110 if (!name)
2111 return ERROR_INVALID_PARAMETER;
2112
2113 /* this one is weird... */
2114 if (!name[0])
2115 return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
2116
2117 if (value && len < 0) len = lstrlenW( value );
2118
2119 rc = msi_get_property( db, name, 0, &sz );
2120 if (!value || (!*value && !len))
2121 {
2122 swprintf( query, ARRAY_SIZE(query), L"DELETE FROM `_Property` WHERE `_Property` = '%s'", name );
2123 }
2124 else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
2125 {
2126 swprintf( query, ARRAY_SIZE(query), L"UPDATE `_Property` SET `Value` = ? WHERE `_Property` = '%s'", name );
2127 row = MSI_CreateRecord(1);
2128 msi_record_set_string( row, 1, value, len );
2129 }
2130 else
2131 {
2132 lstrcpyW( query, L"INSERT INTO `_Property` (`_Property`,`Value`) VALUES (?,?)" );
2133 row = MSI_CreateRecord(2);
2134 msi_record_set_string( row, 1, name, -1 );
2135 msi_record_set_string( row, 2, value, len );
2136 }
2137
2138 rc = MSI_DatabaseOpenViewW(db, query, &view);
2139 if (rc == ERROR_SUCCESS)
2140 {
2141 rc = MSI_ViewExecute(view, row);
2142 MSI_ViewClose(view);
2143 msiobj_release(&view->hdr);
2144 }
2145 if (row) msiobj_release(&row->hdr);
2146 return rc;
2147 }
2148
MsiSetPropertyW(MSIHANDLE hInstall,LPCWSTR szName,LPCWSTR szValue)2149 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
2150 {
2151 MSIPACKAGE *package;
2152 UINT ret;
2153
2154 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
2155 if( !package )
2156 {
2157 MSIHANDLE remote;
2158
2159 if (!(remote = msi_get_remote(hInstall)))
2160 return ERROR_INVALID_HANDLE;
2161
2162 __TRY
2163 {
2164 ret = remote_SetProperty(remote, szName, szValue);
2165 }
2166 __EXCEPT(rpc_filter)
2167 {
2168 ret = GetExceptionCode();
2169 }
2170 __ENDTRY
2171
2172 return ret;
2173 }
2174
2175 ret = msi_set_property( package->db, szName, szValue, -1 );
2176 if (ret == ERROR_SUCCESS && !wcscmp( szName, L"SourceDir" ))
2177 msi_reset_source_folders( package );
2178
2179 msiobj_release( &package->hdr );
2180 return ret;
2181 }
2182
get_property_row(MSIDATABASE * db,const WCHAR * name)2183 static MSIRECORD *get_property_row( MSIDATABASE *db, const WCHAR *name )
2184 {
2185 MSIRECORD *rec, *row = NULL;
2186 MSIQUERY *view;
2187 UINT r;
2188 WCHAR *buffer;
2189 int length;
2190
2191 if (!name || !*name)
2192 return NULL;
2193
2194 if (!wcscmp(name, L"Date"))
2195 {
2196 length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0);
2197 if (!length)
2198 return NULL;
2199 buffer = malloc(length * sizeof(WCHAR));
2200 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length);
2201
2202 row = MSI_CreateRecord(1);
2203 if (!row)
2204 {
2205 free(buffer);
2206 return NULL;
2207 }
2208 MSI_RecordSetStringW(row, 1, buffer);
2209 free(buffer);
2210 return row;
2211 }
2212 else if (!wcscmp(name, L"Time"))
2213 {
2214 length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0);
2215 if (!length)
2216 return NULL;
2217 buffer = malloc(length * sizeof(WCHAR));
2218 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length);
2219
2220 row = MSI_CreateRecord(1);
2221 if (!row)
2222 {
2223 free(buffer);
2224 return NULL;
2225 }
2226 MSI_RecordSetStringW(row, 1, buffer);
2227 free(buffer);
2228 return row;
2229 }
2230
2231 rec = MSI_CreateRecord(1);
2232 if (!rec)
2233 return NULL;
2234
2235 MSI_RecordSetStringW(rec, 1, name);
2236
2237 r = MSI_DatabaseOpenViewW(db, L"SELECT `Value` FROM `_Property` WHERE `_Property`=?", &view);
2238 if (r == ERROR_SUCCESS)
2239 {
2240 MSI_ViewExecute(view, rec);
2241 MSI_ViewFetch(view, &row);
2242 MSI_ViewClose(view);
2243 msiobj_release(&view->hdr);
2244 }
2245 msiobj_release(&rec->hdr);
2246 return row;
2247 }
2248
2249 /* internal function, not compatible with MsiGetPropertyW */
msi_get_property(MSIDATABASE * db,LPCWSTR szName,LPWSTR szValueBuf,LPDWORD pchValueBuf)2250 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
2251 LPWSTR szValueBuf, LPDWORD pchValueBuf )
2252 {
2253 MSIRECORD *row;
2254 UINT rc = ERROR_FUNCTION_FAILED;
2255
2256 TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
2257
2258 row = get_property_row( db, szName );
2259
2260 if (*pchValueBuf > 0)
2261 szValueBuf[0] = 0;
2262
2263 if (row)
2264 {
2265 rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
2266 msiobj_release(&row->hdr);
2267 }
2268
2269 if (rc == ERROR_SUCCESS)
2270 TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf),
2271 debugstr_w(szName));
2272 else if (rc == ERROR_MORE_DATA)
2273 TRACE( "need %lu sized buffer for %s\n", *pchValueBuf, debugstr_w(szName) );
2274 else
2275 {
2276 *pchValueBuf = 0;
2277 TRACE("property %s not found\n", debugstr_w(szName));
2278 }
2279
2280 return rc;
2281 }
2282
msi_dup_property(MSIDATABASE * db,LPCWSTR prop)2283 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
2284 {
2285 DWORD sz = 0;
2286 LPWSTR str;
2287 UINT r;
2288
2289 r = msi_get_property(db, prop, NULL, &sz);
2290 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2291 return NULL;
2292
2293 sz++;
2294 str = malloc(sz * sizeof(WCHAR));
2295 r = msi_get_property(db, prop, str, &sz);
2296 if (r != ERROR_SUCCESS)
2297 {
2298 free(str);
2299 str = NULL;
2300 }
2301
2302 return str;
2303 }
2304
msi_get_property_int(MSIDATABASE * db,LPCWSTR prop,int def)2305 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
2306 {
2307 LPWSTR str = msi_dup_property( db, prop );
2308 int val = str ? wcstol(str, NULL, 10) : def;
2309 free(str);
2310 return val;
2311 }
2312
MsiGetPropertyA(MSIHANDLE hinst,const char * name,char * buf,DWORD * sz)2313 UINT WINAPI MsiGetPropertyA(MSIHANDLE hinst, const char *name, char *buf, DWORD *sz)
2314 {
2315 const WCHAR *value = L"";
2316 MSIPACKAGE *package;
2317 MSIRECORD *row;
2318 WCHAR *nameW;
2319 int len = 0;
2320 UINT r;
2321
2322 if (!name)
2323 return ERROR_INVALID_PARAMETER;
2324
2325 if (!(nameW = strdupAtoW(name)))
2326 return ERROR_OUTOFMEMORY;
2327
2328 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
2329 if (!package)
2330 {
2331 WCHAR *value = NULL, *tmp;
2332 MSIHANDLE remote;
2333 DWORD len;
2334
2335 if (!(remote = msi_get_remote(hinst)))
2336 {
2337 free(nameW);
2338 return ERROR_INVALID_HANDLE;
2339 }
2340
2341 __TRY
2342 {
2343 r = remote_GetProperty(remote, nameW, &value, &len);
2344 }
2345 __EXCEPT(rpc_filter)
2346 {
2347 r = GetExceptionCode();
2348 }
2349 __ENDTRY
2350
2351 free(nameW);
2352
2353 if (!r)
2354 {
2355 /* String might contain embedded nulls.
2356 * Native returns the correct size but truncates the string. */
2357 tmp = calloc(1, (len + 1) * sizeof(WCHAR));
2358 if (!tmp)
2359 {
2360 midl_user_free(value);
2361 return ERROR_OUTOFMEMORY;
2362 }
2363 lstrcpyW(tmp, value);
2364
2365 r = msi_strncpyWtoA(tmp, len, buf, sz, TRUE);
2366
2367 free(tmp);
2368 }
2369 midl_user_free(value);
2370 return r;
2371 }
2372
2373 row = get_property_row(package->db, nameW);
2374 if (row)
2375 value = msi_record_get_string(row, 1, &len);
2376
2377 r = msi_strncpyWtoA(value, len, buf, sz, FALSE);
2378
2379 free(nameW);
2380 if (row) msiobj_release(&row->hdr);
2381 msiobj_release(&package->hdr);
2382 return r;
2383 }
2384
MsiGetPropertyW(MSIHANDLE hinst,const WCHAR * name,WCHAR * buf,DWORD * sz)2385 UINT WINAPI MsiGetPropertyW(MSIHANDLE hinst, const WCHAR *name, WCHAR *buf, DWORD *sz)
2386 {
2387 const WCHAR *value = L"";
2388 MSIPACKAGE *package;
2389 MSIRECORD *row;
2390 int len = 0;
2391 UINT r;
2392
2393 if (!name)
2394 return ERROR_INVALID_PARAMETER;
2395
2396 package = msihandle2msiinfo(hinst, MSIHANDLETYPE_PACKAGE);
2397 if (!package)
2398 {
2399 WCHAR *value = NULL, *tmp;
2400 MSIHANDLE remote;
2401 DWORD len;
2402
2403 if (!(remote = msi_get_remote(hinst)))
2404 return ERROR_INVALID_HANDLE;
2405
2406 __TRY
2407 {
2408 r = remote_GetProperty(remote, name, &value, &len);
2409 }
2410 __EXCEPT(rpc_filter)
2411 {
2412 r = GetExceptionCode();
2413 }
2414 __ENDTRY
2415
2416 if (!r)
2417 {
2418 /* String might contain embedded nulls.
2419 * Native returns the correct size but truncates the string. */
2420 tmp = calloc(1, (len + 1) * sizeof(WCHAR));
2421 if (!tmp)
2422 {
2423 midl_user_free(value);
2424 return ERROR_OUTOFMEMORY;
2425 }
2426 lstrcpyW(tmp, value);
2427
2428 r = msi_strncpyW(tmp, len, buf, sz);
2429
2430 free(tmp);
2431 }
2432 midl_user_free(value);
2433 return r;
2434 }
2435
2436 row = get_property_row(package->db, name);
2437 if (row)
2438 value = msi_record_get_string(row, 1, &len);
2439
2440 r = msi_strncpyW(value, len, buf, sz);
2441
2442 if (row) msiobj_release(&row->hdr);
2443 msiobj_release(&package->hdr);
2444 return r;
2445 }
2446
s_remote_GetActiveDatabase(MSIHANDLE hinst)2447 MSIHANDLE __cdecl s_remote_GetActiveDatabase(MSIHANDLE hinst)
2448 {
2449 return MsiGetActiveDatabase(hinst);
2450 }
2451
s_remote_GetProperty(MSIHANDLE hinst,LPCWSTR property,LPWSTR * value,DWORD * size)2452 UINT __cdecl s_remote_GetProperty(MSIHANDLE hinst, LPCWSTR property, LPWSTR *value, DWORD *size)
2453 {
2454 WCHAR empty[1];
2455 UINT r;
2456
2457 *size = 0;
2458 r = MsiGetPropertyW(hinst, property, empty, size);
2459 if (r == ERROR_MORE_DATA)
2460 {
2461 ++*size;
2462 *value = midl_user_allocate(*size * sizeof(WCHAR));
2463 if (!*value)
2464 return ERROR_OUTOFMEMORY;
2465 r = MsiGetPropertyW(hinst, property, *value, size);
2466 }
2467 return r;
2468 }
2469
s_remote_SetProperty(MSIHANDLE hinst,LPCWSTR property,LPCWSTR value)2470 UINT __cdecl s_remote_SetProperty(MSIHANDLE hinst, LPCWSTR property, LPCWSTR value)
2471 {
2472 return MsiSetPropertyW(hinst, property, value);
2473 }
2474
s_remote_ProcessMessage(MSIHANDLE hinst,INSTALLMESSAGE message,struct wire_record * remote_rec)2475 int __cdecl s_remote_ProcessMessage(MSIHANDLE hinst, INSTALLMESSAGE message, struct wire_record *remote_rec)
2476 {
2477 MSIHANDLE rec;
2478 int ret;
2479 UINT r;
2480
2481 if ((r = unmarshal_record(remote_rec, &rec)))
2482 return r;
2483
2484 ret = MsiProcessMessage(hinst, message, rec);
2485
2486 MsiCloseHandle(rec);
2487 return ret;
2488 }
2489
s_remote_DoAction(MSIHANDLE hinst,LPCWSTR action)2490 UINT __cdecl s_remote_DoAction(MSIHANDLE hinst, LPCWSTR action)
2491 {
2492 return MsiDoActionW(hinst, action);
2493 }
2494
s_remote_Sequence(MSIHANDLE hinst,LPCWSTR table,int sequence)2495 UINT __cdecl s_remote_Sequence(MSIHANDLE hinst, LPCWSTR table, int sequence)
2496 {
2497 return MsiSequenceW(hinst, table, sequence);
2498 }
2499
s_remote_GetTargetPath(MSIHANDLE hinst,LPCWSTR folder,LPWSTR * value)2500 UINT __cdecl s_remote_GetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value)
2501 {
2502 WCHAR empty[1];
2503 DWORD size = 0;
2504 UINT r;
2505
2506 r = MsiGetTargetPathW(hinst, folder, empty, &size);
2507 if (r == ERROR_MORE_DATA)
2508 {
2509 *value = midl_user_allocate(++size * sizeof(WCHAR));
2510 if (!*value)
2511 return ERROR_OUTOFMEMORY;
2512 r = MsiGetTargetPathW(hinst, folder, *value, &size);
2513 }
2514 return r;
2515 }
2516
s_remote_SetTargetPath(MSIHANDLE hinst,LPCWSTR folder,LPCWSTR value)2517 UINT __cdecl s_remote_SetTargetPath(MSIHANDLE hinst, LPCWSTR folder, LPCWSTR value)
2518 {
2519 return MsiSetTargetPathW(hinst, folder, value);
2520 }
2521
s_remote_GetSourcePath(MSIHANDLE hinst,LPCWSTR folder,LPWSTR * value)2522 UINT __cdecl s_remote_GetSourcePath(MSIHANDLE hinst, LPCWSTR folder, LPWSTR *value)
2523 {
2524 WCHAR empty[1];
2525 DWORD size = 1;
2526 UINT r;
2527
2528 r = MsiGetSourcePathW(hinst, folder, empty, &size);
2529 if (r == ERROR_MORE_DATA)
2530 {
2531 *value = midl_user_allocate(++size * sizeof(WCHAR));
2532 if (!*value)
2533 return ERROR_OUTOFMEMORY;
2534 r = MsiGetSourcePathW(hinst, folder, *value, &size);
2535 }
2536 return r;
2537 }
2538
s_remote_GetMode(MSIHANDLE hinst,MSIRUNMODE mode)2539 BOOL __cdecl s_remote_GetMode(MSIHANDLE hinst, MSIRUNMODE mode)
2540 {
2541 return MsiGetMode(hinst, mode);
2542 }
2543
s_remote_SetMode(MSIHANDLE hinst,MSIRUNMODE mode,BOOL state)2544 UINT __cdecl s_remote_SetMode(MSIHANDLE hinst, MSIRUNMODE mode, BOOL state)
2545 {
2546 return MsiSetMode(hinst, mode, state);
2547 }
2548
s_remote_GetFeatureState(MSIHANDLE hinst,LPCWSTR feature,INSTALLSTATE * installed,INSTALLSTATE * action)2549 UINT __cdecl s_remote_GetFeatureState(MSIHANDLE hinst, LPCWSTR feature,
2550 INSTALLSTATE *installed, INSTALLSTATE *action)
2551 {
2552 return MsiGetFeatureStateW(hinst, feature, installed, action);
2553 }
2554
s_remote_SetFeatureState(MSIHANDLE hinst,LPCWSTR feature,INSTALLSTATE state)2555 UINT __cdecl s_remote_SetFeatureState(MSIHANDLE hinst, LPCWSTR feature, INSTALLSTATE state)
2556 {
2557 return MsiSetFeatureStateW(hinst, feature, state);
2558 }
2559
s_remote_GetComponentState(MSIHANDLE hinst,LPCWSTR component,INSTALLSTATE * installed,INSTALLSTATE * action)2560 UINT __cdecl s_remote_GetComponentState(MSIHANDLE hinst, LPCWSTR component,
2561 INSTALLSTATE *installed, INSTALLSTATE *action)
2562 {
2563 return MsiGetComponentStateW(hinst, component, installed, action);
2564 }
2565
s_remote_SetComponentState(MSIHANDLE hinst,LPCWSTR component,INSTALLSTATE state)2566 UINT __cdecl s_remote_SetComponentState(MSIHANDLE hinst, LPCWSTR component, INSTALLSTATE state)
2567 {
2568 return MsiSetComponentStateW(hinst, component, state);
2569 }
2570
s_remote_GetLanguage(MSIHANDLE hinst)2571 LANGID __cdecl s_remote_GetLanguage(MSIHANDLE hinst)
2572 {
2573 return MsiGetLanguage(hinst);
2574 }
2575
s_remote_SetInstallLevel(MSIHANDLE hinst,int level)2576 UINT __cdecl s_remote_SetInstallLevel(MSIHANDLE hinst, int level)
2577 {
2578 return MsiSetInstallLevel(hinst, level);
2579 }
2580
s_remote_FormatRecord(MSIHANDLE hinst,struct wire_record * remote_rec,LPWSTR * value)2581 UINT __cdecl s_remote_FormatRecord(MSIHANDLE hinst, struct wire_record *remote_rec, LPWSTR *value)
2582 {
2583 WCHAR empty[1];
2584 DWORD size = 0;
2585 MSIHANDLE rec;
2586 UINT r;
2587
2588 if ((r = unmarshal_record(remote_rec, &rec)))
2589 return r;
2590
2591 r = MsiFormatRecordW(hinst, rec, empty, &size);
2592 if (r == ERROR_MORE_DATA)
2593 {
2594 *value = midl_user_allocate(++size * sizeof(WCHAR));
2595 if (!*value)
2596 {
2597 MsiCloseHandle(rec);
2598 return ERROR_OUTOFMEMORY;
2599 }
2600 r = MsiFormatRecordW(hinst, rec, *value, &size);
2601 }
2602
2603 MsiCloseHandle(rec);
2604 return r;
2605 }
2606
s_remote_EvaluateCondition(MSIHANDLE hinst,LPCWSTR condition)2607 MSICONDITION __cdecl s_remote_EvaluateCondition(MSIHANDLE hinst, LPCWSTR condition)
2608 {
2609 return MsiEvaluateConditionW(hinst, condition);
2610 }
2611
s_remote_GetFeatureCost(MSIHANDLE hinst,LPCWSTR feature,MSICOSTTREE cost_tree,INSTALLSTATE state,INT * cost)2612 UINT __cdecl s_remote_GetFeatureCost(MSIHANDLE hinst, LPCWSTR feature,
2613 MSICOSTTREE cost_tree, INSTALLSTATE state, INT *cost)
2614 {
2615 return MsiGetFeatureCostW(hinst, feature, cost_tree, state, cost);
2616 }
2617
s_remote_EnumComponentCosts(MSIHANDLE hinst,LPCWSTR component,DWORD index,INSTALLSTATE state,LPWSTR drive,INT * cost,INT * temp)2618 UINT __cdecl s_remote_EnumComponentCosts(MSIHANDLE hinst, LPCWSTR component,
2619 DWORD index, INSTALLSTATE state, LPWSTR drive, INT *cost, INT *temp)
2620 {
2621 DWORD size = 3;
2622 return MsiEnumComponentCostsW(hinst, component, index, state, drive, &size, cost, temp);
2623 }
2624
msi_package_add_info(MSIPACKAGE * package,DWORD context,DWORD options,LPCWSTR property,LPWSTR value)2625 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
2626 LPCWSTR property, LPWSTR value)
2627 {
2628 MSISOURCELISTINFO *info;
2629
2630 LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry )
2631 {
2632 if (!wcscmp( info->value, value )) return ERROR_SUCCESS;
2633 }
2634
2635 info = malloc(sizeof(MSISOURCELISTINFO));
2636 if (!info)
2637 return ERROR_OUTOFMEMORY;
2638
2639 info->context = context;
2640 info->options = options;
2641 info->property = property;
2642 info->value = wcsdup(value);
2643 list_add_head(&package->sourcelist_info, &info->entry);
2644
2645 return ERROR_SUCCESS;
2646 }
2647
msi_package_add_media_disk(MSIPACKAGE * package,DWORD context,DWORD options,DWORD disk_id,LPWSTR volume_label,LPWSTR disk_prompt)2648 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
2649 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
2650 {
2651 MSIMEDIADISK *disk;
2652
2653 LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry )
2654 {
2655 if (disk->disk_id == disk_id) return ERROR_SUCCESS;
2656 }
2657
2658 disk = malloc(sizeof(MSIMEDIADISK));
2659 if (!disk)
2660 return ERROR_OUTOFMEMORY;
2661
2662 disk->context = context;
2663 disk->options = options;
2664 disk->disk_id = disk_id;
2665 disk->volume_label = wcsdup(volume_label);
2666 disk->disk_prompt = wcsdup(disk_prompt);
2667 list_add_head(&package->sourcelist_media, &disk->entry);
2668
2669 return ERROR_SUCCESS;
2670 }
2671