msi: Don't leak memory on failure.
[wine.git] / dlls / msi / package.c
blob2f6027b815eb4b45ca15b8f9b636eaca7bf248d5
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2004 Aric Stewart for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #define COBJMACROS
25 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
33 #include "msi.h"
34 #include "msiquery.h"
35 #include "objidl.h"
36 #include "wincrypt.h"
37 #include "winuser.h"
38 #include "wininet.h"
39 #include "winver.h"
40 #include "urlmon.h"
41 #include "shlobj.h"
42 #include "wine/unicode.h"
43 #include "objbase.h"
44 #include "msidefs.h"
45 #include "sddl.h"
47 #include "msipriv.h"
48 #include "msiserver.h"
49 #include "resource.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(msi);
53 static void free_feature( MSIFEATURE *feature )
55 struct list *item, *cursor;
57 LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
59 FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
60 list_remove( &fl->entry );
61 msi_free( fl );
64 LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
66 ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
67 list_remove( &cl->entry );
68 msi_free( cl );
70 msi_free( feature->Feature );
71 msi_free( feature->Feature_Parent );
72 msi_free( feature->Directory );
73 msi_free( feature->Description );
74 msi_free( feature->Title );
75 msi_free( feature );
78 static void free_folder( MSIFOLDER *folder )
80 struct list *item, *cursor;
82 LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
84 FolderList *fl = LIST_ENTRY( item, FolderList, entry );
85 list_remove( &fl->entry );
86 msi_free( fl );
88 msi_free( folder->Parent );
89 msi_free( folder->Directory );
90 msi_free( folder->TargetDefault );
91 msi_free( folder->SourceLongPath );
92 msi_free( folder->SourceShortPath );
93 msi_free( folder->ResolvedTarget );
94 msi_free( folder->ResolvedSource );
95 msi_free( folder );
98 static void free_extension( MSIEXTENSION *ext )
100 struct list *item, *cursor;
102 LIST_FOR_EACH_SAFE( item, cursor, &ext->verbs )
104 MSIVERB *verb = LIST_ENTRY( item, MSIVERB, entry );
106 list_remove( &verb->entry );
107 msi_free( verb->Verb );
108 msi_free( verb->Command );
109 msi_free( verb->Argument );
110 msi_free( verb );
113 msi_free( ext->Extension );
114 msi_free( ext->ProgIDText );
115 msi_free( ext );
118 static void free_assembly( MSIASSEMBLY *assembly )
120 msi_free( assembly->feature );
121 msi_free( assembly->manifest );
122 msi_free( assembly->application );
123 msi_free( assembly->display_name );
124 if (assembly->tempdir) RemoveDirectoryW( assembly->tempdir );
125 msi_free( assembly->tempdir );
126 msi_free( assembly );
129 void msi_free_action_script( MSIPACKAGE *package, UINT script )
131 UINT i;
132 for (i = 0; i < package->script_actions_count[script]; i++)
133 msi_free( package->script_actions[script][i] );
135 msi_free( package->script_actions[script] );
136 package->script_actions[script] = NULL;
137 package->script_actions_count[script] = 0;
140 static void free_package_structures( MSIPACKAGE *package )
142 struct list *item, *cursor;
143 int i;
145 LIST_FOR_EACH_SAFE( item, cursor, &package->features )
147 MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
148 list_remove( &feature->entry );
149 free_feature( feature );
152 LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
154 MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
155 list_remove( &folder->entry );
156 free_folder( folder );
159 LIST_FOR_EACH_SAFE( item, cursor, &package->files )
161 MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
163 list_remove( &file->entry );
164 msi_free( file->File );
165 msi_free( file->FileName );
166 msi_free( file->ShortName );
167 msi_free( file->LongName );
168 msi_free( file->Version );
169 msi_free( file->Language );
170 if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
171 msi_free( file->TargetPath );
172 msi_free( file );
175 LIST_FOR_EACH_SAFE( item, cursor, &package->components )
177 MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
179 list_remove( &comp->entry );
180 msi_free( comp->Component );
181 msi_free( comp->ComponentId );
182 msi_free( comp->Directory );
183 msi_free( comp->Condition );
184 msi_free( comp->KeyPath );
185 msi_free( comp->FullKeypath );
186 if (comp->assembly) free_assembly( comp->assembly );
187 msi_free( comp );
190 LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
192 MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
194 list_remove( &patch->entry );
195 msi_free( patch->path );
196 msi_free( patch );
199 /* clean up extension, progid, class and verb structures */
200 LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
202 MSICLASS *cls = LIST_ENTRY( item, MSICLASS, entry );
204 list_remove( &cls->entry );
205 msi_free( cls->clsid );
206 msi_free( cls->Context );
207 msi_free( cls->Description );
208 msi_free( cls->FileTypeMask );
209 msi_free( cls->IconPath );
210 msi_free( cls->DefInprocHandler );
211 msi_free( cls->DefInprocHandler32 );
212 msi_free( cls->Argument );
213 msi_free( cls->ProgIDText );
214 msi_free( cls );
217 LIST_FOR_EACH_SAFE( item, cursor, &package->extensions )
219 MSIEXTENSION *ext = LIST_ENTRY( item, MSIEXTENSION, entry );
221 list_remove( &ext->entry );
222 free_extension( ext );
225 LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
227 MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
229 list_remove( &progid->entry );
230 msi_free( progid->ProgID );
231 msi_free( progid->Description );
232 msi_free( progid->IconPath );
233 msi_free( progid );
236 LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
238 MSIMIME *mt = LIST_ENTRY( item, MSIMIME, entry );
240 list_remove( &mt->entry );
241 msi_free( mt->suffix );
242 msi_free( mt->clsid );
243 msi_free( mt->ContentType );
244 msi_free( mt );
247 LIST_FOR_EACH_SAFE( item, cursor, &package->appids )
249 MSIAPPID *appid = LIST_ENTRY( item, MSIAPPID, entry );
251 list_remove( &appid->entry );
252 msi_free( appid->AppID );
253 msi_free( appid->RemoteServerName );
254 msi_free( appid->LocalServer );
255 msi_free( appid->ServiceParameters );
256 msi_free( appid->DllSurrogate );
257 msi_free( appid );
260 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_info )
262 MSISOURCELISTINFO *info = LIST_ENTRY( item, MSISOURCELISTINFO, entry );
264 list_remove( &info->entry );
265 msi_free( info->value );
266 msi_free( info );
269 LIST_FOR_EACH_SAFE( item, cursor, &package->sourcelist_media )
271 MSIMEDIADISK *info = LIST_ENTRY( item, MSIMEDIADISK, entry );
273 list_remove( &info->entry );
274 msi_free( info->volume_label );
275 msi_free( info->disk_prompt );
276 msi_free( info );
279 for (i = 0; i < SCRIPT_MAX; i++)
280 msi_free_action_script( package, i );
282 for (i = 0; i < package->unique_actions_count; i++)
283 msi_free( package->unique_actions[i] );
284 msi_free( package->unique_actions);
286 LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
288 MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
290 list_remove( &binary->entry );
291 if (binary->module)
292 FreeLibrary( binary->module );
293 if (!DeleteFileW( binary->tmpfile ))
294 ERR("failed to delete %s (%u)\n", debugstr_w(binary->tmpfile), GetLastError());
295 msi_free( binary->source );
296 msi_free( binary->tmpfile );
297 msi_free( binary );
300 LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
302 MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
304 list_remove( &cab->entry );
305 IStorage_Release( cab->storage );
306 msi_free( cab->stream );
307 msi_free( cab );
310 LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
312 MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
314 list_remove( &patch->entry );
315 if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
317 ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError());
319 msi_free_patchinfo( patch );
322 msi_free( package->BaseURL );
323 msi_free( package->PackagePath );
324 msi_free( package->ProductCode );
325 msi_free( package->ActionFormat );
326 msi_free( package->LastAction );
327 msi_free( package->LastActionTemplate );
328 msi_free( package->langids );
330 /* cleanup control event subscriptions */
331 msi_event_cleanup_all_subscriptions( package );
334 static void MSI_FreePackage( MSIOBJECTHDR *arg)
336 MSIPACKAGE *package = (MSIPACKAGE *)arg;
338 msi_destroy_assembly_caches( package );
340 if( package->dialog )
341 msi_dialog_destroy( package->dialog );
343 msiobj_release( &package->db->hdr );
344 free_package_structures(package);
345 CloseHandle( package->log_file );
347 if (package->delete_on_close) DeleteFileW( package->localfile );
348 msi_free( package->localfile );
349 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
352 static UINT create_temp_property_table(MSIPACKAGE *package)
354 static const WCHAR query[] = {
355 'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
356 '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
357 '`','_','P','r','o','p','e','r','t','y','`',' ',
358 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
359 'T','E','M','P','O','R','A','R','Y',',',' ',
360 '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
361 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
362 ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
363 '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
364 MSIQUERY *view;
365 UINT rc;
367 rc = MSI_DatabaseOpenViewW(package->db, query, &view);
368 if (rc != ERROR_SUCCESS)
369 return rc;
371 rc = MSI_ViewExecute(view, 0);
372 MSI_ViewClose(view);
373 msiobj_release(&view->hdr);
374 return rc;
377 UINT msi_clone_properties( MSIDATABASE *db )
379 static const WCHAR query_select[] = {
380 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
381 '`','P','r','o','p','e','r','t','y','`',0};
382 static const WCHAR query_insert[] = {
383 'I','N','S','E','R','T',' ','I','N','T','O',' ',
384 '`','_','P','r','o','p','e','r','t','y','`',' ',
385 '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
386 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
387 static const WCHAR query_update[] = {
388 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
389 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
390 'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0};
391 MSIQUERY *view_select;
392 UINT rc;
394 rc = MSI_DatabaseOpenViewW( db, query_select, &view_select );
395 if (rc != ERROR_SUCCESS)
396 return rc;
398 rc = MSI_ViewExecute( view_select, 0 );
399 if (rc != ERROR_SUCCESS)
401 MSI_ViewClose( view_select );
402 msiobj_release( &view_select->hdr );
403 return rc;
406 while (1)
408 MSIQUERY *view_insert, *view_update;
409 MSIRECORD *rec_select;
411 rc = MSI_ViewFetch( view_select, &rec_select );
412 if (rc != ERROR_SUCCESS)
413 break;
415 rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert );
416 if (rc != ERROR_SUCCESS)
418 msiobj_release( &rec_select->hdr );
419 continue;
422 rc = MSI_ViewExecute( view_insert, rec_select );
423 MSI_ViewClose( view_insert );
424 msiobj_release( &view_insert->hdr );
425 if (rc != ERROR_SUCCESS)
427 MSIRECORD *rec_update;
429 TRACE("insert failed, trying update\n");
431 rc = MSI_DatabaseOpenViewW( db, query_update, &view_update );
432 if (rc != ERROR_SUCCESS)
434 WARN("open view failed %u\n", rc);
435 msiobj_release( &rec_select->hdr );
436 continue;
439 rec_update = MSI_CreateRecord( 2 );
440 MSI_RecordCopyField( rec_select, 1, rec_update, 2 );
441 MSI_RecordCopyField( rec_select, 2, rec_update, 1 );
442 rc = MSI_ViewExecute( view_update, rec_update );
443 if (rc != ERROR_SUCCESS)
444 WARN("update failed %u\n", rc);
446 MSI_ViewClose( view_update );
447 msiobj_release( &view_update->hdr );
448 msiobj_release( &rec_update->hdr );
451 msiobj_release( &rec_select->hdr );
454 MSI_ViewClose( view_select );
455 msiobj_release( &view_select->hdr );
456 return rc;
460 * set_installed_prop
462 * Sets the "Installed" property to indicate that
463 * the product is installed for the current user.
465 static UINT set_installed_prop( MSIPACKAGE *package )
467 HKEY hkey;
468 UINT r;
470 if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
472 r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
473 if (r == ERROR_SUCCESS)
475 RegCloseKey( hkey );
476 msi_set_property( package->db, szInstalled, szOne, -1 );
478 return r;
481 static UINT set_user_sid_prop( MSIPACKAGE *package )
483 SID_NAME_USE use;
484 LPWSTR user_name;
485 LPWSTR sid_str = NULL, dom = NULL;
486 DWORD size, dom_size;
487 PSID psid = NULL;
488 UINT r = ERROR_FUNCTION_FAILED;
490 size = 0;
491 GetUserNameW( NULL, &size );
493 user_name = msi_alloc( (size + 1) * sizeof(WCHAR) );
494 if (!user_name)
495 return ERROR_OUTOFMEMORY;
497 if (!GetUserNameW( user_name, &size ))
498 goto done;
500 size = 0;
501 dom_size = 0;
502 LookupAccountNameW( NULL, user_name, NULL, &size, NULL, &dom_size, &use );
504 psid = msi_alloc( size );
505 dom = msi_alloc( dom_size*sizeof (WCHAR) );
506 if (!psid || !dom)
508 r = ERROR_OUTOFMEMORY;
509 goto done;
512 if (!LookupAccountNameW( NULL, user_name, psid, &size, dom, &dom_size, &use ))
513 goto done;
515 if (!ConvertSidToStringSidW( psid, &sid_str ))
516 goto done;
518 r = msi_set_property( package->db, szUserSID, sid_str, -1 );
520 done:
521 LocalFree( sid_str );
522 msi_free( dom );
523 msi_free( psid );
524 msi_free( user_name );
526 return r;
529 static LPWSTR get_fusion_filename(MSIPACKAGE *package)
531 HKEY netsetup;
532 LONG res;
533 LPWSTR file = NULL;
534 DWORD index = 0, size;
535 WCHAR ver[MAX_PATH];
536 WCHAR name[MAX_PATH];
537 WCHAR windir[MAX_PATH];
539 static const WCHAR fusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
540 static const WCHAR sub[] = {
541 'S','o','f','t','w','a','r','e','\\',
542 'M','i','c','r','o','s','o','f','t','\\',
543 'N','E','T',' ','F','r','a','m','e','w','o','r','k',' ','S','e','t','u','p','\\',
544 'N','D','P',0
546 static const WCHAR subdir[] = {
547 'M','i','c','r','o','s','o','f','t','.','N','E','T','\\',
548 'F','r','a','m','e','w','o','r','k','\\',0
551 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub, 0, KEY_ENUMERATE_SUB_KEYS, &netsetup);
552 if (res != ERROR_SUCCESS)
553 return NULL;
555 GetWindowsDirectoryW(windir, MAX_PATH);
557 ver[0] = '\0';
558 size = MAX_PATH;
559 while (RegEnumKeyExW(netsetup, index, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
561 index++;
563 /* verify existence of fusion.dll .Net 3.0 does not install a new one */
564 if (strcmpW( ver, name ) < 0)
566 LPWSTR check;
567 size = lstrlenW(windir) + lstrlenW(subdir) + lstrlenW(name) +lstrlenW(fusion) + 3;
568 check = msi_alloc(size * sizeof(WCHAR));
570 if (!check)
572 msi_free(file);
573 return NULL;
576 lstrcpyW(check, windir);
577 lstrcatW(check, szBackSlash);
578 lstrcatW(check, subdir);
579 lstrcatW(check, name);
580 lstrcatW(check, szBackSlash);
581 lstrcatW(check, fusion);
583 if(GetFileAttributesW(check) != INVALID_FILE_ATTRIBUTES)
585 msi_free(file);
586 file = check;
587 lstrcpyW(ver, name);
589 else
590 msi_free(check);
594 RegCloseKey(netsetup);
595 return file;
598 typedef struct tagLANGANDCODEPAGE
600 WORD wLanguage;
601 WORD wCodePage;
602 } LANGANDCODEPAGE;
604 static void set_msi_assembly_prop(MSIPACKAGE *package)
606 UINT val_len;
607 DWORD size, handle;
608 LPVOID version = NULL;
609 WCHAR buf[MAX_PATH];
610 LPWSTR fusion, verstr;
611 LANGANDCODEPAGE *translate;
613 static const WCHAR netasm[] = {
614 'M','s','i','N','e','t','A','s','s','e','m','b','l','y','S','u','p','p','o','r','t',0
616 static const WCHAR translation[] = {
617 '\\','V','a','r','F','i','l','e','I','n','f','o',
618 '\\','T','r','a','n','s','l','a','t','i','o','n',0
620 static const WCHAR verfmt[] = {
621 '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
622 '\\','%','0','4','x','%','0','4','x',
623 '\\','P','r','o','d','u','c','t','V','e','r','s','i','o','n',0
626 fusion = get_fusion_filename(package);
627 if (!fusion)
628 return;
630 size = GetFileVersionInfoSizeW(fusion, &handle);
631 if (!size)
632 goto done;
634 version = msi_alloc(size);
635 if (!version)
636 goto done;
638 if (!GetFileVersionInfoW(fusion, handle, size, version))
639 goto done;
641 if (!VerQueryValueW(version, translation, (LPVOID *)&translate, &val_len))
642 goto done;
644 sprintfW(buf, verfmt, translate[0].wLanguage, translate[0].wCodePage);
646 if (!VerQueryValueW(version, buf, (LPVOID *)&verstr, &val_len))
647 goto done;
649 if (!val_len || !verstr)
650 goto done;
652 msi_set_property( package->db, netasm, verstr, -1 );
654 done:
655 msi_free(fusion);
656 msi_free(version);
659 static VOID set_installer_properties(MSIPACKAGE *package)
661 WCHAR *ptr;
662 OSVERSIONINFOEXW OSVersion;
663 MEMORYSTATUSEX msex;
664 DWORD verval, len;
665 WCHAR pth[MAX_PATH], verstr[11], bufstr[22];
666 HDC dc;
667 HKEY hkey;
668 LPWSTR username, companyname;
669 SYSTEM_INFO sys_info;
670 LANGID langid;
672 static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
673 static const WCHAR szProgramFilesFolder[] = {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
674 static const WCHAR szCommonAppDataFolder[] = {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
675 static const WCHAR szFavoritesFolder[] = {'F','a','v','o','r','i','t','e','s','F','o','l','d','e','r',0};
676 static const WCHAR szFontsFolder[] = {'F','o','n','t','s','F','o','l','d','e','r',0};
677 static const WCHAR szSendToFolder[] = {'S','e','n','d','T','o','F','o','l','d','e','r',0};
678 static const WCHAR szStartMenuFolder[] = {'S','t','a','r','t','M','e','n','u','F','o','l','d','e','r',0};
679 static const WCHAR szStartupFolder[] = {'S','t','a','r','t','u','p','F','o','l','d','e','r',0};
680 static const WCHAR szTemplateFolder[] = {'T','e','m','p','l','a','t','e','F','o','l','d','e','r',0};
681 static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
682 static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
683 static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
684 static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0};
685 static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
686 static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
687 static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
688 static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
689 static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
690 static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0};
691 static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0};
692 static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0};
693 static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0};
694 static const WCHAR szFormat[] = {'%','u',0};
695 static const WCHAR szFormat2[] = {'%','u','.','%','u',0};
696 static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0};
697 static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0};
698 static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
699 static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 };
700 static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
701 static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
702 static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
703 static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
704 static const WCHAR szIntFormat[] = {'%','d',0};
705 static const WCHAR szMsiAMD64[] = { 'M','s','i','A','M','D','6','4',0 };
706 static const WCHAR szMsix64[] = { 'M','s','i','x','6','4',0 };
707 static const WCHAR szSystem64Folder[] = { 'S','y','s','t','e','m','6','4','F','o','l','d','e','r',0 };
708 static const WCHAR szCommonFiles64Folder[] = { 'C','o','m','m','o','n','F','i','l','e','s','6','4','F','o','l','d','e','r',0 };
709 static const WCHAR szProgramFiles64Folder[] = { 'P','r','o','g','r','a','m','F','i','l','e','s','6','4','F','o','l','d','e','r',0 };
710 static const WCHAR szVersionNT64[] = { 'V','e','r','s','i','o','n','N','T','6','4',0 };
711 static const WCHAR szUserInfo[] = {
712 'S','O','F','T','W','A','R','E','\\',
713 'M','i','c','r','o','s','o','f','t','\\',
714 'M','S',' ','S','e','t','u','p',' ','(','A','C','M','E',')','\\',
715 'U','s','e','r',' ','I','n','f','o',0
717 static const WCHAR szDefName[] = { 'D','e','f','N','a','m','e',0 };
718 static const WCHAR szDefCompany[] = { 'D','e','f','C','o','m','p','a','n','y',0 };
719 static const WCHAR szCurrentVersion[] = {
720 'S','O','F','T','W','A','R','E','\\',
721 'M','i','c','r','o','s','o','f','t','\\',
722 'W','i','n','d','o','w','s',' ','N','T','\\',
723 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0
725 static const WCHAR szRegisteredUser[] = {'R','e','g','i','s','t','e','r','e','d','O','w','n','e','r',0};
726 static const WCHAR szRegisteredOrganization[] = {
727 'R','e','g','i','s','t','e','r','e','d','O','r','g','a','n','i','z','a','t','i','o','n',0
729 static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
730 static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
731 static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
732 static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
733 static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
734 static const WCHAR szLogonUser[] = {'L','o','g','o','n','U','s','e','r',0};
735 static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0};
736 static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0};
737 static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0};
738 static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
741 * Other things that probably should be set:
743 * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
744 * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
747 SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
748 strcatW(pth, szBackSlash);
749 msi_set_property( package->db, szCommonAppDataFolder, pth, -1 );
751 SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
752 strcatW(pth, szBackSlash);
753 msi_set_property( package->db, szFavoritesFolder, pth, -1 );
755 SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
756 strcatW(pth, szBackSlash);
757 msi_set_property( package->db, szFontsFolder, pth, -1 );
759 SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
760 strcatW(pth, szBackSlash);
761 msi_set_property( package->db, szSendToFolder, pth, -1 );
763 SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
764 strcatW(pth, szBackSlash);
765 msi_set_property( package->db, szStartMenuFolder, pth, -1 );
767 SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
768 strcatW(pth, szBackSlash);
769 msi_set_property( package->db, szStartupFolder, pth, -1 );
771 SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
772 strcatW(pth, szBackSlash);
773 msi_set_property( package->db, szTemplateFolder, pth, -1 );
775 SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
776 strcatW(pth, szBackSlash);
777 msi_set_property( package->db, szDesktopFolder, pth, -1 );
779 /* FIXME: set to AllUsers profile path if ALLUSERS is set */
780 SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
781 strcatW(pth, szBackSlash);
782 msi_set_property( package->db, szProgramMenuFolder, pth, -1 );
784 SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
785 strcatW(pth, szBackSlash);
786 msi_set_property( package->db, szAdminToolsFolder, pth, -1 );
788 SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
789 strcatW(pth, szBackSlash);
790 msi_set_property( package->db, szAppDataFolder, pth, -1 );
792 SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
793 strcatW(pth, szBackSlash);
794 msi_set_property( package->db, szSystemFolder, pth, -1 );
795 msi_set_property( package->db, szSystem16Folder, pth, -1 );
797 SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
798 strcatW(pth, szBackSlash);
799 msi_set_property( package->db, szLocalAppDataFolder, pth, -1 );
801 SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
802 strcatW(pth, szBackSlash);
803 msi_set_property( package->db, szMyPicturesFolder, pth, -1 );
805 SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
806 strcatW(pth, szBackSlash);
807 msi_set_property( package->db, szPersonalFolder, pth, -1 );
809 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
810 strcatW(pth, szBackSlash);
811 msi_set_property( package->db, szWindowsFolder, pth, -1 );
813 SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
814 strcatW(pth, szBackSlash);
815 msi_set_property( package->db, szPrintHoodFolder, pth, -1 );
817 SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
818 strcatW(pth, szBackSlash);
819 msi_set_property( package->db, szNetHoodFolder, pth, -1 );
821 SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
822 strcatW(pth, szBackSlash);
823 msi_set_property( package->db, szRecentFolder, pth, -1 );
825 /* Physical Memory is specified in MB. Using total amount. */
826 msex.dwLength = sizeof(msex);
827 GlobalMemoryStatusEx( &msex );
828 len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
829 msi_set_property( package->db, szPhysicalMemory, bufstr, len );
831 SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
832 ptr = strchrW(pth,'\\');
833 if (ptr) *(ptr + 1) = 0;
834 msi_set_property( package->db, szWindowsVolume, pth, -1 );
836 len = GetTempPathW(MAX_PATH, pth);
837 msi_set_property( package->db, szTempFolder, pth, len );
839 /* in a wine environment the user is always admin and privileged */
840 msi_set_property( package->db, szAdminUser, szOne, -1 );
841 msi_set_property( package->db, szPrivileged, szOne, -1 );
843 /* set the os things */
844 OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
845 GetVersionExW((OSVERSIONINFOW *)&OSVersion);
846 verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
847 len = sprintfW( verstr, szFormat, verval );
848 switch (OSVersion.dwPlatformId)
850 case VER_PLATFORM_WIN32_WINDOWS:
851 msi_set_property( package->db, szVersion9x, verstr, len );
852 break;
853 case VER_PLATFORM_WIN32_NT:
854 msi_set_property( package->db, szVersionNT, verstr, len );
855 len = sprintfW( bufstr, szFormat,OSVersion.wProductType );
856 msi_set_property( package->db, szMsiNTProductType, bufstr, len );
857 break;
859 len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber );
860 msi_set_property( package->db, szWindowsBuild, bufstr, len );
861 len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor );
862 msi_set_property( package->db, szServicePackLevel, bufstr, len );
864 len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION );
865 msi_set_property( package->db, szVersionMsi, bufstr, len );
866 len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 );
867 msi_set_property( package->db, szVersionDatabase, bufstr, len );
869 GetNativeSystemInfo( &sys_info );
870 len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
871 msi_set_property( package->db, szIntel, bufstr, len );
872 if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
874 GetSystemDirectoryW( pth, MAX_PATH );
875 PathAddBackslashW( pth );
876 msi_set_property( package->db, szSystemFolder, pth, -1 );
878 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
879 PathAddBackslashW( pth );
880 msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
882 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
883 PathAddBackslashW( pth );
884 msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
886 else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
888 msi_set_property( package->db, szMsiAMD64, bufstr, -1 );
889 msi_set_property( package->db, szMsix64, bufstr, -1 );
890 msi_set_property( package->db, szVersionNT64, verstr, -1 );
892 GetSystemDirectoryW( pth, MAX_PATH );
893 PathAddBackslashW( pth );
894 msi_set_property( package->db, szSystem64Folder, pth, -1 );
896 GetSystemWow64DirectoryW( pth, MAX_PATH );
897 PathAddBackslashW( pth );
898 msi_set_property( package->db, szSystemFolder, pth, -1 );
900 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
901 PathAddBackslashW( pth );
902 msi_set_property( package->db, szProgramFiles64Folder, pth, -1 );
904 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
905 PathAddBackslashW( pth );
906 msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
908 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
909 PathAddBackslashW( pth );
910 msi_set_property( package->db, szCommonFiles64Folder, pth, -1 );
912 SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
913 PathAddBackslashW( pth );
914 msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
917 /* Screen properties. */
918 dc = GetDC(0);
919 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) );
920 msi_set_property( package->db, szScreenX, bufstr, len );
921 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) );
922 msi_set_property( package->db, szScreenY, bufstr, len );
923 len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) );
924 msi_set_property( package->db, szColorBits, bufstr, len );
925 ReleaseDC(0, dc);
927 /* USERNAME and COMPANYNAME */
928 username = msi_dup_property( package->db, szUSERNAME );
929 companyname = msi_dup_property( package->db, szCOMPANYNAME );
931 if ((!username || !companyname) &&
932 RegOpenKeyW( HKEY_CURRENT_USER, szUserInfo, &hkey ) == ERROR_SUCCESS)
934 if (!username &&
935 (username = msi_reg_get_val_str( hkey, szDefName )))
936 msi_set_property( package->db, szUSERNAME, username, -1 );
937 if (!companyname &&
938 (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
939 msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
940 CloseHandle( hkey );
942 if ((!username || !companyname) &&
943 RegOpenKeyW( HKEY_LOCAL_MACHINE, szCurrentVersion, &hkey ) == ERROR_SUCCESS)
945 if (!username &&
946 (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
947 msi_set_property( package->db, szUSERNAME, username, -1 );
948 if (!companyname &&
949 (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization )))
950 msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
951 CloseHandle( hkey );
953 msi_free( username );
954 msi_free( companyname );
956 if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
957 ERR("Failed to set the UserSID property\n");
959 set_msi_assembly_prop( package );
961 langid = GetUserDefaultLangID();
962 len = sprintfW( bufstr, szIntFormat, langid );
963 msi_set_property( package->db, szUserLanguageID, bufstr, len );
965 langid = GetSystemDefaultLangID();
966 len = sprintfW( bufstr, szIntFormat, langid );
967 msi_set_property( package->db, szSystemLangID, bufstr, len );
969 len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) );
970 msi_set_property( package->db, szProductState, bufstr, len );
972 len = 0;
973 if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
975 WCHAR *username;
976 if ((username = msi_alloc( len * sizeof(WCHAR) )))
978 if (GetUserNameW( username, &len ))
979 msi_set_property( package->db, szLogonUser, username, len - 1 );
980 msi_free( username );
983 len = 0;
984 if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
986 WCHAR *computername;
987 if ((computername = msi_alloc( len * sizeof(WCHAR) )))
989 if (GetComputerNameW( computername, &len ))
990 msi_set_property( package->db, szComputerName, computername, len );
991 msi_free( computername );
996 static MSIPACKAGE *msi_alloc_package( void )
998 MSIPACKAGE *package;
1000 package = alloc_msiobject( MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
1001 MSI_FreePackage );
1002 if( package )
1004 list_init( &package->components );
1005 list_init( &package->features );
1006 list_init( &package->files );
1007 list_init( &package->filepatches );
1008 list_init( &package->tempfiles );
1009 list_init( &package->folders );
1010 list_init( &package->subscriptions );
1011 list_init( &package->appids );
1012 list_init( &package->classes );
1013 list_init( &package->mimes );
1014 list_init( &package->extensions );
1015 list_init( &package->progids );
1016 list_init( &package->RunningActions );
1017 list_init( &package->sourcelist_info );
1018 list_init( &package->sourcelist_media );
1019 list_init( &package->patches );
1020 list_init( &package->binaries );
1021 list_init( &package->cabinet_streams );
1024 return package;
1027 static UINT msi_load_admin_properties(MSIPACKAGE *package)
1029 BYTE *data;
1030 UINT r, sz;
1032 static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0};
1034 r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz);
1035 if (r != ERROR_SUCCESS)
1036 return r;
1038 r = msi_parse_command_line(package, (WCHAR *)data, TRUE);
1040 msi_free(data);
1041 return r;
1044 void msi_adjust_privilege_properties( MSIPACKAGE *package )
1046 /* FIXME: this should depend on the user's privileges */
1047 if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
1049 TRACE("resetting ALLUSERS property from 2 to 1\n");
1050 msi_set_property( package->db, szAllUsers, szOne, -1 );
1052 msi_set_property( package->db, szAdminUser, szOne, -1 );
1055 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
1057 static const WCHAR fmtW[] = {'%','u',0};
1058 MSIPACKAGE *package;
1059 WCHAR uilevel[11];
1060 int len;
1061 UINT r;
1063 TRACE("%p\n", db);
1065 package = msi_alloc_package();
1066 if (package)
1068 msiobj_addref( &db->hdr );
1069 package->db = db;
1071 package->LastAction = NULL;
1072 package->LastActionTemplate = NULL;
1073 package->LastActionResult = MSI_NULL_INTEGER;
1074 package->WordCount = 0;
1075 package->PackagePath = strdupW( db->path );
1076 package->BaseURL = strdupW( base_url );
1078 create_temp_property_table( package );
1079 msi_clone_properties( package->db );
1080 msi_adjust_privilege_properties( package );
1082 package->ProductCode = msi_dup_property( package->db, szProductCode );
1084 set_installer_properties( package );
1086 package->ui_level = gUILevel;
1087 len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
1088 msi_set_property( package->db, szUILevel, uilevel, len );
1090 r = msi_load_suminfo_properties( package );
1091 if (r != ERROR_SUCCESS)
1093 msiobj_release( &package->hdr );
1094 return NULL;
1097 if (package->WordCount & msidbSumInfoSourceTypeAdminImage)
1098 msi_load_admin_properties( package );
1100 package->log_file = INVALID_HANDLE_VALUE;
1101 package->script = SCRIPT_NONE;
1103 return package;
1106 UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
1108 LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
1109 DWORD size = 0;
1110 HRESULT hr;
1112 /* call will always fail, because size is 0,
1113 * but will return ERROR_FILE_NOT_FOUND first
1114 * if the file doesn't exist
1116 GetUrlCacheEntryInfoW( szUrl, NULL, &size );
1117 if ( GetLastError() != ERROR_FILE_NOT_FOUND )
1119 cache_entry = msi_alloc( size );
1120 if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) )
1122 UINT error = GetLastError();
1123 msi_free( cache_entry );
1124 return error;
1127 lstrcpyW( filename, cache_entry->lpszLocalFileName );
1128 msi_free( cache_entry );
1129 return ERROR_SUCCESS;
1132 hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL );
1133 if ( FAILED(hr) )
1135 WARN("failed to download %s to cache file\n", debugstr_w(szUrl));
1136 return ERROR_FUNCTION_FAILED;
1139 return ERROR_SUCCESS;
1142 UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
1144 static const WCHAR szInstaller[] = {
1145 '\\','I','n','s','t','a','l','l','e','r','\\',0};
1146 static const WCHAR fmt[] = {'%','x',0};
1147 DWORD time, len, i, offset;
1148 HANDLE handle;
1150 time = GetTickCount();
1151 GetWindowsDirectoryW( path, MAX_PATH );
1152 strcatW( path, szInstaller );
1153 CreateDirectoryW( path, NULL );
1155 len = strlenW(path);
1156 for (i = 0; i < 0x10000; i++)
1158 offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff );
1159 memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) );
1160 handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
1161 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1162 if (handle != INVALID_HANDLE_VALUE)
1164 CloseHandle(handle);
1165 break;
1167 if (GetLastError() != ERROR_FILE_EXISTS &&
1168 GetLastError() != ERROR_SHARING_VIOLATION)
1169 return ERROR_FUNCTION_FAILED;
1172 return ERROR_SUCCESS;
1175 static enum platform parse_platform( const WCHAR *str )
1177 if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL;
1178 else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64;
1179 else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64;
1180 else if (!strcmpW( str, szARM )) return PLATFORM_ARM;
1181 return PLATFORM_UNKNOWN;
1184 static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
1186 WCHAR *template, *p, *q, *platform;
1187 DWORD i, count;
1189 package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
1190 TRACE("version: %d\n", package->version);
1192 template = msi_suminfo_dup_string( si, PID_TEMPLATE );
1193 if (!template)
1194 return ERROR_SUCCESS; /* native accepts missing template property */
1196 TRACE("template: %s\n", debugstr_w(template));
1198 p = strchrW( template, ';' );
1199 if (!p)
1201 WARN("invalid template string %s\n", debugstr_w(template));
1202 msi_free( template );
1203 return ERROR_PATCH_PACKAGE_INVALID;
1205 *p = 0;
1206 platform = template;
1207 if ((q = strchrW( platform, ',' ))) *q = 0;
1208 package->platform = parse_platform( platform );
1209 while (package->platform == PLATFORM_UNKNOWN && q)
1211 platform = q + 1;
1212 if ((q = strchrW( platform, ',' ))) *q = 0;
1213 package->platform = parse_platform( platform );
1215 if (package->platform == PLATFORM_UNKNOWN)
1217 WARN("unknown platform %s\n", debugstr_w(template));
1218 msi_free( template );
1219 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1221 p++;
1222 if (!*p)
1224 msi_free( template );
1225 return ERROR_SUCCESS;
1227 count = 1;
1228 for (q = p; (q = strchrW( q, ',' )); q++) count++;
1230 package->langids = msi_alloc( count * sizeof(LANGID) );
1231 if (!package->langids)
1233 msi_free( template );
1234 return ERROR_OUTOFMEMORY;
1237 i = 0;
1238 while (*p)
1240 q = strchrW( p, ',' );
1241 if (q) *q = 0;
1242 package->langids[i] = atoiW( p );
1243 if (!q) break;
1244 p = q + 1;
1245 i++;
1247 package->num_langids = i + 1;
1249 msi_free( template );
1250 return ERROR_SUCCESS;
1253 static UINT validate_package( MSIPACKAGE *package )
1255 UINT i;
1257 if (package->platform == PLATFORM_INTEL64)
1258 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1259 #ifndef __arm__
1260 if (package->platform == PLATFORM_ARM)
1261 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1262 #endif
1263 if (package->platform == PLATFORM_X64)
1265 if (!is_64bit && !is_wow64)
1266 return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
1267 if (package->version < 200)
1268 return ERROR_INSTALL_PACKAGE_INVALID;
1270 if (!package->num_langids)
1272 return ERROR_SUCCESS;
1274 for (i = 0; i < package->num_langids; i++)
1276 LANGID langid = package->langids[i];
1278 if (PRIMARYLANGID( langid ) == LANG_NEUTRAL)
1280 langid = MAKELANGID( PRIMARYLANGID( GetSystemDefaultLangID() ), SUBLANGID( langid ) );
1282 if (SUBLANGID( langid ) == SUBLANG_NEUTRAL)
1284 langid = MAKELANGID( PRIMARYLANGID( langid ), SUBLANGID( GetSystemDefaultLangID() ) );
1286 if (IsValidLocale( langid, LCID_INSTALLED ))
1287 return ERROR_SUCCESS;
1289 return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
1292 static WCHAR *get_product_code( MSIDATABASE *db )
1294 static const WCHAR query[] = {
1295 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
1296 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ',
1297 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=',
1298 '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0};
1299 MSIQUERY *view;
1300 MSIRECORD *rec;
1301 WCHAR *ret = NULL;
1303 if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
1305 return NULL;
1307 if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
1309 MSI_ViewClose( view );
1310 msiobj_release( &view->hdr );
1311 return NULL;
1313 if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
1315 ret = strdupW( MSI_RecordGetString( rec, 1 ) );
1316 msiobj_release( &rec->hdr );
1318 MSI_ViewClose( view );
1319 msiobj_release( &view->hdr );
1320 return ret;
1323 static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile )
1325 MSIINSTALLCONTEXT context;
1326 HKEY product_key, props_key;
1327 WCHAR *registered_package = NULL, unsquashed[GUID_SIZE];
1328 UINT r;
1330 r = msi_locate_product( product, &context );
1331 if (r != ERROR_SUCCESS)
1332 return r;
1334 r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE );
1335 if (r != ERROR_SUCCESS)
1336 return r;
1338 r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
1339 if (r != ERROR_SUCCESS)
1341 RegCloseKey( product_key );
1342 return r;
1344 r = ERROR_FUNCTION_FAILED;
1345 registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW );
1346 if (!registered_package)
1347 goto done;
1349 unsquash_guid( registered_package, unsquashed );
1350 if (!strcmpiW( package, unsquashed ))
1352 WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
1353 if (!filename)
1354 goto done;
1356 strcpyW( localfile, filename );
1357 msi_free( filename );
1358 r = ERROR_SUCCESS;
1360 done:
1361 msi_free( registered_package );
1362 RegCloseKey( props_key );
1363 RegCloseKey( product_key );
1364 return r;
1367 static WCHAR *get_package_code( MSIDATABASE *db )
1369 WCHAR *ret;
1370 MSISUMMARYINFO *si;
1371 UINT r;
1373 r = msi_get_suminfo( db->storage, 0, &si );
1374 if (r != ERROR_SUCCESS)
1376 r = msi_get_db_suminfo( db, 0, &si );
1377 if (r != ERROR_SUCCESS)
1379 WARN("failed to load summary info %u\n", r);
1380 return NULL;
1383 ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
1384 msiobj_release( &si->hdr );
1385 return ret;
1388 static UINT get_local_package( const WCHAR *filename, WCHAR *localfile )
1390 WCHAR *product_code, *package_code;
1391 MSIDATABASE *db;
1392 UINT r;
1394 if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS)
1396 if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES)
1397 return ERROR_FILE_NOT_FOUND;
1398 return r;
1400 if (!(product_code = get_product_code( db )))
1402 msiobj_release( &db->hdr );
1403 return ERROR_INSTALL_PACKAGE_INVALID;
1405 if (!(package_code = get_package_code( db )))
1407 msi_free( product_code );
1408 msiobj_release( &db->hdr );
1409 return ERROR_INSTALL_PACKAGE_INVALID;
1411 r = get_registered_local_package( product_code, package_code, localfile );
1412 msi_free( package_code );
1413 msi_free( product_code );
1414 msiobj_release( &db->hdr );
1415 return r;
1418 UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package )
1420 UINT r;
1422 if (UrlIsW( package, URLIS_URL ))
1423 r = msi_set_property( db, szOriginalDatabase, package, -1 );
1424 else if (package[0] == '#')
1425 r = msi_set_property( db, szOriginalDatabase, db->path, -1 );
1426 else
1428 DWORD len;
1429 WCHAR *path;
1431 if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError();
1432 if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
1433 len = GetFullPathNameW( package, len, path, NULL );
1434 r = msi_set_property( db, szOriginalDatabase, path, len );
1435 msi_free( path );
1437 return r;
1440 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
1442 static const WCHAR dotmsi[] = {'.','m','s','i',0};
1443 MSIDATABASE *db;
1444 MSIPACKAGE *package;
1445 MSIHANDLE handle;
1446 MSIRECORD *data_row, *info_row;
1447 LPWSTR ptr, base_url = NULL;
1448 UINT r;
1449 WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
1450 LPCWSTR file = szPackage;
1451 DWORD index = 0;
1452 MSISUMMARYINFO *si;
1453 BOOL delete_on_close = FALSE;
1454 LPWSTR productname;
1455 WCHAR *info_template;
1457 TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
1459 MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
1461 localfile[0] = 0;
1462 if( szPackage[0] == '#' )
1464 handle = atoiW(&szPackage[1]);
1465 db = msihandle2msiinfo( handle, MSIHANDLETYPE_DATABASE );
1466 if( !db )
1468 IWineMsiRemoteDatabase *remote_database;
1470 remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( handle );
1471 if ( !remote_database )
1472 return ERROR_INVALID_HANDLE;
1474 IWineMsiRemoteDatabase_Release( remote_database );
1475 WARN("MsiOpenPackage not allowed during a custom action!\n");
1477 return ERROR_FUNCTION_FAILED;
1480 else
1482 if ( UrlIsW( szPackage, URLIS_URL ) )
1484 r = msi_download_file( szPackage, cachefile );
1485 if (r != ERROR_SUCCESS)
1486 return r;
1488 file = cachefile;
1490 base_url = strdupW( szPackage );
1491 if (!base_url)
1492 return ERROR_OUTOFMEMORY;
1494 ptr = strrchrW( base_url, '/' );
1495 if (ptr) *(ptr + 1) = '\0';
1497 r = get_local_package( file, localfile );
1498 if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
1500 r = msi_create_empty_local_file( localfile, dotmsi );
1501 if (r != ERROR_SUCCESS)
1503 msi_free ( base_url );
1504 return r;
1507 if (!CopyFileW( file, localfile, FALSE ))
1509 r = GetLastError();
1510 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
1511 DeleteFileW( localfile );
1512 msi_free ( base_url );
1513 return r;
1515 delete_on_close = TRUE;
1517 TRACE("opening package %s\n", debugstr_w( localfile ));
1518 r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
1519 if (r != ERROR_SUCCESS)
1521 msi_free ( base_url );
1522 return r;
1525 package = MSI_CreatePackage( db, base_url );
1526 msi_free( base_url );
1527 msiobj_release( &db->hdr );
1528 if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
1529 package->localfile = strdupW( localfile );
1530 package->delete_on_close = delete_on_close;
1532 r = msi_get_suminfo( db->storage, 0, &si );
1533 if (r != ERROR_SUCCESS)
1535 r = msi_get_db_suminfo( db, 0, &si );
1536 if (r != ERROR_SUCCESS)
1538 WARN("failed to load summary info\n");
1539 msiobj_release( &package->hdr );
1540 return ERROR_INSTALL_PACKAGE_INVALID;
1543 r = parse_suminfo( si, package );
1544 msiobj_release( &si->hdr );
1545 if (r != ERROR_SUCCESS)
1547 WARN("failed to parse summary info %u\n", r);
1548 msiobj_release( &package->hdr );
1549 return r;
1551 r = validate_package( package );
1552 if (r != ERROR_SUCCESS)
1554 msiobj_release( &package->hdr );
1555 return r;
1557 msi_set_property( package->db, szDatabase, db->path, -1 );
1558 set_installed_prop( package );
1559 msi_set_context( package );
1561 while (1)
1563 WCHAR patch_code[GUID_SIZE];
1564 r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
1565 MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
1566 if (r != ERROR_SUCCESS)
1567 break;
1569 TRACE("found registered patch %s\n", debugstr_w(patch_code));
1571 r = msi_apply_registered_patch( package, patch_code );
1572 if (r != ERROR_SUCCESS)
1574 ERR("registered patch failed to apply %u\n", r);
1575 msiobj_release( &package->hdr );
1576 return r;
1578 index++;
1580 if (index) msi_adjust_privilege_properties( package );
1582 r = msi_set_original_database_property( package->db, szPackage );
1583 if (r != ERROR_SUCCESS)
1585 msiobj_release( &package->hdr );
1586 return r;
1588 if (gszLogFile)
1589 package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1590 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
1592 /* FIXME: when should these messages be sent? */
1593 data_row = MSI_CreateRecord(3);
1594 if (!data_row)
1595 return ERROR_OUTOFMEMORY;
1596 MSI_RecordSetStringW(data_row, 0, NULL);
1597 MSI_RecordSetInteger(data_row, 1, 0);
1598 MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
1599 MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
1600 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
1602 info_row = MSI_CreateRecord(0);
1603 if (!info_row)
1605 msiobj_release(&data_row->hdr);
1606 return ERROR_OUTOFMEMORY;
1608 info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
1609 MSI_RecordSetStringW(info_row, 0, info_template);
1610 msi_free(info_template);
1611 MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
1613 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
1615 productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
1616 MSI_RecordSetInteger(data_row, 1, 1);
1617 MSI_RecordSetStringW(data_row, 2, productname);
1618 MSI_RecordSetStringW(data_row, 3, NULL);
1619 MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
1621 msi_free(productname);
1622 msiobj_release(&info_row->hdr);
1623 msiobj_release(&data_row->hdr);
1625 *pPackage = package;
1626 return ERROR_SUCCESS;
1629 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1631 MSIPACKAGE *package = NULL;
1632 UINT ret;
1634 TRACE("%s %08x %p\n", debugstr_w(szPackage), dwOptions, phPackage );
1636 if( !szPackage || !phPackage )
1637 return ERROR_INVALID_PARAMETER;
1639 if ( !*szPackage )
1641 FIXME("Should create an empty database and package\n");
1642 return ERROR_FUNCTION_FAILED;
1645 if( dwOptions )
1646 FIXME("dwOptions %08x not supported\n", dwOptions);
1648 ret = MSI_OpenPackageW( szPackage, &package );
1649 if( ret == ERROR_SUCCESS )
1651 *phPackage = alloc_msihandle( &package->hdr );
1652 if (! *phPackage)
1653 ret = ERROR_NOT_ENOUGH_MEMORY;
1654 msiobj_release( &package->hdr );
1656 else
1657 MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
1659 return ret;
1662 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
1664 return MsiOpenPackageExW( szPackage, 0, phPackage );
1667 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
1669 LPWSTR szwPack = NULL;
1670 UINT ret;
1672 if( szPackage )
1674 szwPack = strdupAtoW( szPackage );
1675 if( !szwPack )
1676 return ERROR_OUTOFMEMORY;
1679 ret = MsiOpenPackageExW( szwPack, dwOptions, phPackage );
1681 msi_free( szwPack );
1683 return ret;
1686 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
1688 return MsiOpenPackageExA( szPackage, 0, phPackage );
1691 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
1693 MSIPACKAGE *package;
1694 MSIHANDLE handle = 0;
1695 IUnknown *remote_unk;
1696 IWineMsiRemotePackage *remote_package;
1698 TRACE("(%d)\n",hInstall);
1700 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
1701 if( package)
1703 handle = alloc_msihandle( &package->db->hdr );
1704 msiobj_release( &package->hdr );
1706 else if ((remote_unk = msi_get_remote(hInstall)))
1708 if (IUnknown_QueryInterface(remote_unk, &IID_IWineMsiRemotePackage,
1709 (LPVOID *)&remote_package) == S_OK)
1711 IWineMsiRemotePackage_GetActiveDatabase(remote_package, &handle);
1712 IWineMsiRemotePackage_Release(remote_package);
1714 else
1716 WARN("remote handle %d is not a package\n", hInstall);
1718 IUnknown_Release(remote_unk);
1721 return handle;
1724 static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
1726 static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
1727 static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
1728 static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
1729 static const WCHAR szWindows_Installer[] =
1730 {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0};
1732 if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
1733 return 0;
1735 /* todo: check if message needs additional styles (topmost/foreground/modality?) */
1737 switch (eMessageType & 0xff000000)
1739 case INSTALLMESSAGE_FATALEXIT:
1740 case INSTALLMESSAGE_ERROR:
1741 case INSTALLMESSAGE_OUTOFDISKSPACE:
1742 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1743 if (!(eMessageType & MB_ICONMASK))
1744 eMessageType |= MB_ICONEXCLAMATION;
1745 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
1746 case INSTALLMESSAGE_WARNING:
1747 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1748 if (!(eMessageType & MB_ICONMASK))
1749 eMessageType |= MB_ICONASTERISK;
1750 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
1751 case INSTALLMESSAGE_USER:
1752 if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
1753 if (!(eMessageType & MB_ICONMASK))
1754 eMessageType |= MB_USERICON;
1755 return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
1756 case INSTALLMESSAGE_INFO:
1757 case INSTALLMESSAGE_INITIALIZE:
1758 case INSTALLMESSAGE_TERMINATE:
1759 case INSTALLMESSAGE_INSTALLSTART:
1760 case INSTALLMESSAGE_INSTALLEND:
1761 return 0;
1762 case INSTALLMESSAGE_SHOWDIALOG:
1764 LPWSTR dialog = msi_dup_record_field(record, 0);
1765 INT rc = ACTION_DialogBox(package, dialog);
1766 msi_free(dialog);
1767 return rc;
1769 case INSTALLMESSAGE_ACTIONSTART:
1771 LPWSTR deformatted;
1772 MSIRECORD *uirow = MSI_CreateRecord(1);
1773 if (!uirow) return -1;
1774 deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
1775 MSI_RecordSetStringW(uirow, 1, deformatted);
1776 msi_event_fire(package, szActionText, uirow);
1778 msi_free(deformatted);
1779 msiobj_release(&uirow->hdr);
1780 return 1;
1782 case INSTALLMESSAGE_ACTIONDATA:
1784 MSIRECORD *uirow = MSI_CreateRecord(1);
1785 if (!uirow) return -1;
1786 MSI_RecordSetStringW(uirow, 1, message);
1787 msi_event_fire(package, szActionData, uirow);
1788 msiobj_release(&uirow->hdr);
1790 if (package->action_progress_increment)
1792 uirow = MSI_CreateRecord(2);
1793 if (!uirow) return -1;
1794 MSI_RecordSetInteger(uirow, 1, 2);
1795 MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
1796 msi_event_fire(package, szSetProgress, uirow);
1797 msiobj_release(&uirow->hdr);
1799 return 1;
1801 case INSTALLMESSAGE_PROGRESS:
1802 msi_event_fire(package, szSetProgress, record);
1803 return 1;
1804 case INSTALLMESSAGE_COMMONDATA:
1805 switch (MSI_RecordGetInteger(record, 1))
1807 case 0:
1808 case 1:
1809 /* do nothing */
1810 return 0;
1811 default:
1812 /* fall through */
1815 default:
1816 FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
1817 return 0;
1821 static const WCHAR szActionNotFound[] = {'D','E','B','U','G',':',' ','E','r','r','o','r',' ','[','1',']',':',' ',' ','A','c','t','i','o','n',' ','n','o','t',' ','f','o','u','n','d',':',' ','[','2',']',0};
1823 static const struct
1825 int id;
1826 const WCHAR *text;
1828 internal_errors[] =
1830 {2726, szActionNotFound},
1834 static LPCWSTR get_internal_error_message(int error)
1836 int i = 0;
1838 while (internal_errors[i].id != 0)
1840 if (internal_errors[i].id == error)
1841 return internal_errors[i].text;
1842 i++;
1845 FIXME("missing error message %d\n", error);
1846 return NULL;
1849 /* Returned string must be freed */
1850 LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
1852 static const WCHAR query[] =
1853 {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ',
1854 'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ',
1855 '`','E','r','r','o','r','`',' ','=',' ','%','i',0};
1856 MSIRECORD *record;
1857 LPWSTR ret = NULL;
1859 if ((record = MSI_QueryGetRecord(db, query, error)))
1861 ret = msi_dup_record_field(record, 1);
1862 msiobj_release(&record->hdr);
1864 else if (error < 2000)
1866 int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
1867 if (len)
1869 ret = msi_alloc((len + 1) * sizeof(WCHAR));
1870 LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
1872 else
1873 ret = NULL;
1876 return ret;
1879 INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
1881 LPWSTR message = {0};
1882 DWORD len;
1883 DWORD log_type = 1 << (eMessageType >> 24);
1884 UINT res;
1885 INT rc = 0;
1886 char *msg;
1888 TRACE("%x\n", eMessageType);
1889 if (TRACE_ON(msi)) dump_record(record);
1891 if (!package || !record)
1892 message = NULL;
1893 else {
1894 res = MSI_FormatRecordW(package, record, message, &len);
1895 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
1896 return res;
1897 len++;
1898 message = msi_alloc(len * sizeof(WCHAR));
1899 if (!message) return ERROR_OUTOFMEMORY;
1900 MSI_FormatRecordW(package, record, message, &len);
1903 /* convert it to ASCII */
1904 len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
1905 msg = msi_alloc( len );
1906 WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
1908 if (gUIHandlerRecord && (gUIFilterRecord & log_type))
1910 MSIHANDLE rec = alloc_msihandle(&record->hdr);
1911 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n",
1912 gUIHandlerRecord, gUIContextRecord, eMessageType, rec);
1913 rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
1914 MsiCloseHandle( rec );
1916 if (!rc && gUIHandlerW && (gUIFilter & log_type))
1918 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
1919 gUIHandlerW, gUIContext, eMessageType, debugstr_w(message));
1920 rc = gUIHandlerW( gUIContext, eMessageType, message );
1922 else if (!rc && gUIHandlerA && (gUIFilter & log_type))
1924 TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
1925 gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg));
1926 rc = gUIHandlerA( gUIContext, eMessageType, msg );
1929 if (!rc)
1930 rc = internal_ui_handler(package, eMessageType, record, message);
1932 if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
1933 (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
1935 DWORD written;
1936 WriteFile( package->log_file, msg, len - 1, &written, NULL );
1937 WriteFile( package->log_file, "\n", 1, &written, NULL );
1939 msi_free( msg );
1940 msi_free( message );
1942 return rc;
1945 INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
1947 switch (eMessageType & 0xff000000)
1949 case INSTALLMESSAGE_FATALEXIT:
1950 case INSTALLMESSAGE_ERROR:
1951 case INSTALLMESSAGE_WARNING:
1952 case INSTALLMESSAGE_USER:
1953 case INSTALLMESSAGE_INFO:
1954 case INSTALLMESSAGE_OUTOFDISKSPACE:
1955 if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
1957 /* error message */
1959 LPWSTR template;
1960 LPWSTR template_rec = NULL, template_prefix = NULL;
1961 int error = MSI_RecordGetInteger(record, 1);
1963 if (MSI_RecordIsNull(record, 0))
1965 if (error >= 32)
1967 template_rec = msi_get_error_message(package->db, error);
1969 if (!template_rec && error >= 2000)
1971 /* internal error, not localized */
1972 if ((template_rec = (LPWSTR) get_internal_error_message(error)))
1974 MSI_RecordSetStringW(record, 0, template_rec);
1975 MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
1977 template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
1978 MSI_RecordSetStringW(record, 0, template_rec);
1979 MSI_ProcessMessageVerbatim(package, eMessageType, record);
1980 msi_free(template_rec);
1981 return 0;
1985 else
1986 template_rec = msi_dup_record_field(record, 0);
1988 template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
1989 if (!template_prefix) template_prefix = strdupW(szEmpty);
1991 if (!template_rec)
1993 /* always returns 0 */
1994 MSI_RecordSetStringW(record, 0, template_prefix);
1995 MSI_ProcessMessageVerbatim(package, eMessageType, record);
1996 msi_free(template_prefix);
1997 return 0;
2000 template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR));
2001 if (!template) return ERROR_OUTOFMEMORY;
2003 strcpyW(template, template_prefix);
2004 strcatW(template, template_rec);
2005 MSI_RecordSetStringW(record, 0, template);
2007 msi_free(template_prefix);
2008 msi_free(template_rec);
2009 msi_free(template);
2011 break;
2012 case INSTALLMESSAGE_ACTIONSTART:
2014 WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
2015 MSI_RecordSetStringW(record, 0, template);
2016 msi_free(template);
2018 msi_free(package->LastAction);
2019 msi_free(package->LastActionTemplate);
2020 package->LastAction = msi_dup_record_field(record, 1);
2021 if (!package->LastAction) package->LastAction = strdupW(szEmpty);
2022 package->LastActionTemplate = msi_dup_record_field(record, 3);
2023 break;
2025 case INSTALLMESSAGE_ACTIONDATA:
2026 if (package->LastAction && package->LastActionTemplate)
2028 static const WCHAR template_s[] =
2029 {'{','{','%','s',':',' ','}','}','%','s',0};
2030 WCHAR *template;
2032 template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR));
2033 if (!template) return ERROR_OUTOFMEMORY;
2034 sprintfW(template, template_s, package->LastAction, package->LastActionTemplate);
2035 MSI_RecordSetStringW(record, 0, template);
2036 msi_free(template);
2038 break;
2039 case INSTALLMESSAGE_COMMONDATA:
2041 WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA);
2042 MSI_RecordSetStringW(record, 0, template);
2043 msi_free(template);
2045 break;
2048 return MSI_ProcessMessageVerbatim(package, eMessageType, record);
2051 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
2052 MSIHANDLE hRecord)
2054 UINT ret = ERROR_INVALID_HANDLE;
2055 MSIPACKAGE *package = NULL;
2056 MSIRECORD *record = NULL;
2058 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE ||
2059 (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
2060 return -1;
2062 if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA &&
2063 MsiRecordGetInteger(hRecord, 1) != 2)
2064 return -1;
2066 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
2067 if( !package )
2069 HRESULT hr;
2070 IWineMsiRemotePackage *remote_package;
2072 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
2073 if (!remote_package)
2074 return ERROR_INVALID_HANDLE;
2076 hr = IWineMsiRemotePackage_ProcessMessage( remote_package, eMessageType, hRecord );
2078 IWineMsiRemotePackage_Release( remote_package );
2080 if (FAILED(hr))
2082 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
2083 return HRESULT_CODE(hr);
2085 return ERROR_FUNCTION_FAILED;
2088 return ERROR_SUCCESS;
2091 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD );
2092 if( !record )
2093 goto out;
2095 ret = MSI_ProcessMessage( package, eMessageType, record );
2097 out:
2098 msiobj_release( &package->hdr );
2099 if( record )
2100 msiobj_release( &record->hdr );
2102 return ret;
2105 /* property code */
2107 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue )
2109 LPWSTR szwName = NULL, szwValue = NULL;
2110 UINT r = ERROR_OUTOFMEMORY;
2112 szwName = strdupAtoW( szName );
2113 if( szName && !szwName )
2114 goto end;
2116 szwValue = strdupAtoW( szValue );
2117 if( szValue && !szwValue )
2118 goto end;
2120 r = MsiSetPropertyW( hInstall, szwName, szwValue);
2122 end:
2123 msi_free( szwName );
2124 msi_free( szwValue );
2126 return r;
2129 void msi_reset_folders( MSIPACKAGE *package, BOOL source )
2131 MSIFOLDER *folder;
2133 LIST_FOR_EACH_ENTRY( folder, &package->folders, MSIFOLDER, entry )
2135 if ( source )
2137 msi_free( folder->ResolvedSource );
2138 folder->ResolvedSource = NULL;
2140 else
2142 msi_free( folder->ResolvedTarget );
2143 folder->ResolvedTarget = NULL;
2148 UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
2150 static const WCHAR insert_query[] = {
2151 'I','N','S','E','R','T',' ','I','N','T','O',' ',
2152 '`','_','P','r','o','p','e','r','t','y','`',' ',
2153 '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
2154 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
2155 static const WCHAR update_query[] = {
2156 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
2157 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ',
2158 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
2159 static const WCHAR delete_query[] = {
2160 'D','E','L','E','T','E',' ','F','R','O','M',' ',
2161 '`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
2162 '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
2163 MSIQUERY *view;
2164 MSIRECORD *row = NULL;
2165 DWORD sz = 0;
2166 WCHAR query[1024];
2167 UINT rc;
2169 TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len);
2171 if (!name)
2172 return ERROR_INVALID_PARAMETER;
2174 /* this one is weird... */
2175 if (!name[0])
2176 return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
2178 if (value && len < 0) len = strlenW( value );
2180 rc = msi_get_property( db, name, 0, &sz );
2181 if (!value || (!*value && !len))
2183 sprintfW( query, delete_query, name );
2185 else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
2187 sprintfW( query, update_query, name );
2188 row = MSI_CreateRecord(1);
2189 msi_record_set_string( row, 1, value, len );
2191 else
2193 strcpyW( query, insert_query );
2194 row = MSI_CreateRecord(2);
2195 msi_record_set_string( row, 1, name, -1 );
2196 msi_record_set_string( row, 2, value, len );
2199 rc = MSI_DatabaseOpenViewW(db, query, &view);
2200 if (rc == ERROR_SUCCESS)
2202 rc = MSI_ViewExecute(view, row);
2203 MSI_ViewClose(view);
2204 msiobj_release(&view->hdr);
2206 if (row) msiobj_release(&row->hdr);
2207 return rc;
2210 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
2212 MSIPACKAGE *package;
2213 UINT ret;
2215 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
2216 if( !package )
2218 HRESULT hr;
2219 BSTR name = NULL, value = NULL;
2220 IWineMsiRemotePackage *remote_package;
2222 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
2223 if (!remote_package)
2224 return ERROR_INVALID_HANDLE;
2226 name = SysAllocString( szName );
2227 value = SysAllocString( szValue );
2228 if ((!name && szName) || (!value && szValue))
2230 SysFreeString( name );
2231 SysFreeString( value );
2232 IWineMsiRemotePackage_Release( remote_package );
2233 return ERROR_OUTOFMEMORY;
2236 hr = IWineMsiRemotePackage_SetProperty( remote_package, name, value );
2238 SysFreeString( name );
2239 SysFreeString( value );
2240 IWineMsiRemotePackage_Release( remote_package );
2242 if (FAILED(hr))
2244 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
2245 return HRESULT_CODE(hr);
2247 return ERROR_FUNCTION_FAILED;
2250 return ERROR_SUCCESS;
2253 ret = msi_set_property( package->db, szName, szValue, -1 );
2254 if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
2255 msi_reset_folders( package, TRUE );
2257 msiobj_release( &package->hdr );
2258 return ret;
2261 static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
2263 static const WCHAR query[]= {
2264 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
2265 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ',
2266 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0};
2267 MSIRECORD *rec, *row = NULL;
2268 MSIQUERY *view;
2269 UINT r;
2271 static const WCHAR szDate[] = {'D','a','t','e',0};
2272 static const WCHAR szTime[] = {'T','i','m','e',0};
2273 WCHAR *buffer;
2274 int length;
2276 if (!name || !*name)
2277 return NULL;
2279 if (!strcmpW(name, szDate))
2281 length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0);
2282 if (!length)
2283 return NULL;
2284 buffer = msi_alloc(length * sizeof(WCHAR));
2285 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length);
2287 row = MSI_CreateRecord(1);
2288 if (!row)
2290 msi_free(buffer);
2291 return NULL;
2293 MSI_RecordSetStringW(row, 1, buffer);
2294 msi_free(buffer);
2295 return row;
2297 else if (!strcmpW(name, szTime))
2299 length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0);
2300 if (!length)
2301 return NULL;
2302 buffer = msi_alloc(length * sizeof(WCHAR));
2303 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length);
2305 row = MSI_CreateRecord(1);
2306 if (!row)
2308 msi_free(buffer);
2309 return NULL;
2311 MSI_RecordSetStringW(row, 1, buffer);
2312 msi_free(buffer);
2313 return row;
2316 rec = MSI_CreateRecord(1);
2317 if (!rec)
2318 return NULL;
2320 MSI_RecordSetStringW(rec, 1, name);
2322 r = MSI_DatabaseOpenViewW(db, query, &view);
2323 if (r == ERROR_SUCCESS)
2325 MSI_ViewExecute(view, rec);
2326 MSI_ViewFetch(view, &row);
2327 MSI_ViewClose(view);
2328 msiobj_release(&view->hdr);
2330 msiobj_release(&rec->hdr);
2331 return row;
2334 /* internal function, not compatible with MsiGetPropertyW */
2335 UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
2336 LPWSTR szValueBuf, LPDWORD pchValueBuf )
2338 MSIRECORD *row;
2339 UINT rc = ERROR_FUNCTION_FAILED;
2341 TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
2343 row = msi_get_property_row( db, szName );
2345 if (*pchValueBuf > 0)
2346 szValueBuf[0] = 0;
2348 if (row)
2350 rc = MSI_RecordGetStringW(row, 1, szValueBuf, pchValueBuf);
2351 msiobj_release(&row->hdr);
2354 if (rc == ERROR_SUCCESS)
2355 TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf),
2356 debugstr_w(szName));
2357 else if (rc == ERROR_MORE_DATA)
2358 TRACE("need %d sized buffer for %s\n", *pchValueBuf,
2359 debugstr_w(szName));
2360 else
2362 *pchValueBuf = 0;
2363 TRACE("property %s not found\n", debugstr_w(szName));
2366 return rc;
2369 LPWSTR msi_dup_property(MSIDATABASE *db, LPCWSTR prop)
2371 DWORD sz = 0;
2372 LPWSTR str;
2373 UINT r;
2375 r = msi_get_property(db, prop, NULL, &sz);
2376 if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2377 return NULL;
2379 sz++;
2380 str = msi_alloc(sz * sizeof(WCHAR));
2381 r = msi_get_property(db, prop, str, &sz);
2382 if (r != ERROR_SUCCESS)
2384 msi_free(str);
2385 str = NULL;
2388 return str;
2391 int msi_get_property_int( MSIDATABASE *db, LPCWSTR prop, int def )
2393 LPWSTR str = msi_dup_property( db, prop );
2394 int val = str ? atoiW(str) : def;
2395 msi_free(str);
2396 return val;
2399 static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
2400 awstring *szValueBuf, LPDWORD pchValueBuf )
2402 MSIPACKAGE *package;
2403 MSIRECORD *row = NULL;
2404 UINT r = ERROR_FUNCTION_FAILED;
2405 LPCWSTR val = NULL;
2406 DWORD len = 0;
2408 TRACE("%u %s %p %p\n", handle, debugstr_w(name),
2409 szValueBuf->str.w, pchValueBuf );
2411 if (!name)
2412 return ERROR_INVALID_PARAMETER;
2414 package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE );
2415 if (!package)
2417 HRESULT hr;
2418 IWineMsiRemotePackage *remote_package;
2419 LPWSTR value = NULL;
2420 BSTR bname;
2422 remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
2423 if (!remote_package)
2424 return ERROR_INVALID_HANDLE;
2426 bname = SysAllocString( name );
2427 if (!bname)
2429 IWineMsiRemotePackage_Release( remote_package );
2430 return ERROR_OUTOFMEMORY;
2433 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
2434 if (FAILED(hr))
2435 goto done;
2437 len++;
2438 value = msi_alloc(len * sizeof(WCHAR));
2439 if (!value)
2441 r = ERROR_OUTOFMEMORY;
2442 goto done;
2445 hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len );
2446 if (FAILED(hr))
2447 goto done;
2449 r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf );
2451 /* Bug required by Adobe installers */
2452 if (!szValueBuf->unicode && !szValueBuf->str.a)
2453 *pchValueBuf *= sizeof(WCHAR);
2455 done:
2456 IWineMsiRemotePackage_Release(remote_package);
2457 SysFreeString(bname);
2458 msi_free(value);
2460 if (FAILED(hr))
2462 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
2463 return HRESULT_CODE(hr);
2465 return ERROR_FUNCTION_FAILED;
2468 return r;
2471 row = msi_get_property_row( package->db, name );
2472 if (row)
2473 val = msi_record_get_string( row, 1, (int *)&len );
2475 if (!val)
2476 val = szEmpty;
2478 r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf );
2480 if (row)
2481 msiobj_release( &row->hdr );
2482 msiobj_release( &package->hdr );
2484 return r;
2487 UINT WINAPI MsiGetPropertyA( MSIHANDLE hInstall, LPCSTR szName,
2488 LPSTR szValueBuf, LPDWORD pchValueBuf )
2490 awstring val;
2491 LPWSTR name;
2492 UINT r;
2494 val.unicode = FALSE;
2495 val.str.a = szValueBuf;
2497 name = strdupAtoW( szName );
2498 if (szName && !name)
2499 return ERROR_OUTOFMEMORY;
2501 r = MSI_GetProperty( hInstall, name, &val, pchValueBuf );
2502 msi_free( name );
2503 return r;
2506 UINT WINAPI MsiGetPropertyW( MSIHANDLE hInstall, LPCWSTR szName,
2507 LPWSTR szValueBuf, LPDWORD pchValueBuf )
2509 awstring val;
2511 val.unicode = TRUE;
2512 val.str.w = szValueBuf;
2514 return MSI_GetProperty( hInstall, szName, &val, pchValueBuf );
2517 typedef struct _msi_remote_package_impl {
2518 IWineMsiRemotePackage IWineMsiRemotePackage_iface;
2519 MSIHANDLE package;
2520 LONG refs;
2521 } msi_remote_package_impl;
2523 static inline msi_remote_package_impl *impl_from_IWineMsiRemotePackage( IWineMsiRemotePackage *iface )
2525 return CONTAINING_RECORD(iface, msi_remote_package_impl, IWineMsiRemotePackage_iface);
2528 static HRESULT WINAPI mrp_QueryInterface( IWineMsiRemotePackage *iface,
2529 REFIID riid,LPVOID *ppobj)
2531 if( IsEqualCLSID( riid, &IID_IUnknown ) ||
2532 IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) )
2534 IWineMsiRemotePackage_AddRef( iface );
2535 *ppobj = iface;
2536 return S_OK;
2539 return E_NOINTERFACE;
2542 static ULONG WINAPI mrp_AddRef( IWineMsiRemotePackage *iface )
2544 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2546 return InterlockedIncrement( &This->refs );
2549 static ULONG WINAPI mrp_Release( IWineMsiRemotePackage *iface )
2551 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2552 ULONG r;
2554 r = InterlockedDecrement( &This->refs );
2555 if (r == 0)
2557 MsiCloseHandle( This->package );
2558 msi_free( This );
2560 return r;
2563 static HRESULT WINAPI mrp_SetMsiHandle( IWineMsiRemotePackage *iface, MSIHANDLE handle )
2565 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2566 This->package = handle;
2567 return S_OK;
2570 static HRESULT WINAPI mrp_GetActiveDatabase( IWineMsiRemotePackage *iface, MSIHANDLE *handle )
2572 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2573 IWineMsiRemoteDatabase *rdb = NULL;
2574 HRESULT hr;
2575 MSIHANDLE hdb;
2577 hr = create_msi_remote_database( NULL, (LPVOID *)&rdb );
2578 if (FAILED(hr) || !rdb)
2580 ERR("Failed to create remote database\n");
2581 return hr;
2584 hdb = MsiGetActiveDatabase(This->package);
2586 hr = IWineMsiRemoteDatabase_SetMsiHandle( rdb, hdb );
2587 if (FAILED(hr))
2589 ERR("Failed to set the database handle\n");
2590 return hr;
2593 *handle = alloc_msi_remote_handle( (IUnknown *)rdb );
2594 return S_OK;
2597 static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size )
2599 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2600 UINT r = MsiGetPropertyW(This->package, property, value, size);
2601 if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r);
2602 return S_OK;
2605 static HRESULT WINAPI mrp_SetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value )
2607 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2608 UINT r = MsiSetPropertyW(This->package, property, value);
2609 return HRESULT_FROM_WIN32(r);
2612 static HRESULT WINAPI mrp_ProcessMessage( IWineMsiRemotePackage *iface, INSTALLMESSAGE message, MSIHANDLE record )
2614 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2615 UINT r = MsiProcessMessage(This->package, message, record);
2616 return HRESULT_FROM_WIN32(r);
2619 static HRESULT WINAPI mrp_DoAction( IWineMsiRemotePackage *iface, BSTR action )
2621 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2622 UINT r = MsiDoActionW(This->package, action);
2623 return HRESULT_FROM_WIN32(r);
2626 static HRESULT WINAPI mrp_Sequence( IWineMsiRemotePackage *iface, BSTR table, int sequence )
2628 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2629 UINT r = MsiSequenceW(This->package, table, sequence);
2630 return HRESULT_FROM_WIN32(r);
2633 static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
2635 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2636 UINT r = MsiGetTargetPathW(This->package, folder, value, size);
2637 return HRESULT_FROM_WIN32(r);
2640 static HRESULT WINAPI mrp_SetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value)
2642 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2643 UINT r = MsiSetTargetPathW(This->package, folder, value);
2644 return HRESULT_FROM_WIN32(r);
2647 static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
2649 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2650 UINT r = MsiGetSourcePathW(This->package, folder, value, size);
2651 return HRESULT_FROM_WIN32(r);
2654 static HRESULT WINAPI mrp_GetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL *ret )
2656 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2657 *ret = MsiGetMode(This->package, mode);
2658 return S_OK;
2661 static HRESULT WINAPI mrp_SetMode( IWineMsiRemotePackage *iface, MSIRUNMODE mode, BOOL state )
2663 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2664 UINT r = MsiSetMode(This->package, mode, state);
2665 return HRESULT_FROM_WIN32(r);
2668 static HRESULT WINAPI mrp_GetFeatureState( IWineMsiRemotePackage *iface, BSTR feature,
2669 INSTALLSTATE *installed, INSTALLSTATE *action )
2671 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2672 UINT r = MsiGetFeatureStateW(This->package, feature, installed, action);
2673 return HRESULT_FROM_WIN32(r);
2676 static HRESULT WINAPI mrp_SetFeatureState( IWineMsiRemotePackage *iface, BSTR feature, INSTALLSTATE state )
2678 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2679 UINT r = MsiSetFeatureStateW(This->package, feature, state);
2680 return HRESULT_FROM_WIN32(r);
2683 static HRESULT WINAPI mrp_GetComponentState( IWineMsiRemotePackage *iface, BSTR component,
2684 INSTALLSTATE *installed, INSTALLSTATE *action )
2686 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2687 UINT r = MsiGetComponentStateW(This->package, component, installed, action);
2688 return HRESULT_FROM_WIN32(r);
2691 static HRESULT WINAPI mrp_SetComponentState( IWineMsiRemotePackage *iface, BSTR component, INSTALLSTATE state )
2693 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2694 UINT r = MsiSetComponentStateW(This->package, component, state);
2695 return HRESULT_FROM_WIN32(r);
2698 static HRESULT WINAPI mrp_GetLanguage( IWineMsiRemotePackage *iface, LANGID *language )
2700 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2701 *language = MsiGetLanguage(This->package);
2702 return S_OK;
2705 static HRESULT WINAPI mrp_SetInstallLevel( IWineMsiRemotePackage *iface, int level )
2707 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2708 UINT r = MsiSetInstallLevel(This->package, level);
2709 return HRESULT_FROM_WIN32(r);
2712 static HRESULT WINAPI mrp_FormatRecord( IWineMsiRemotePackage *iface, MSIHANDLE record,
2713 BSTR *value)
2715 DWORD size = 0;
2716 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2717 UINT r = MsiFormatRecordW(This->package, record, NULL, &size);
2718 if (r == ERROR_SUCCESS)
2720 *value = SysAllocStringLen(NULL, size);
2721 if (!*value)
2722 return E_OUTOFMEMORY;
2723 size++;
2724 r = MsiFormatRecordW(This->package, record, *value, &size);
2726 return HRESULT_FROM_WIN32(r);
2729 static HRESULT WINAPI mrp_EvaluateCondition( IWineMsiRemotePackage *iface, BSTR condition )
2731 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2732 UINT r = MsiEvaluateConditionW(This->package, condition);
2733 return HRESULT_FROM_WIN32(r);
2736 static HRESULT WINAPI mrp_GetFeatureCost( IWineMsiRemotePackage *iface, BSTR feature,
2737 INT cost_tree, INSTALLSTATE state, INT *cost )
2739 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2740 UINT r = MsiGetFeatureCostW(This->package, feature, cost_tree, state, cost);
2741 return HRESULT_FROM_WIN32(r);
2744 static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component,
2745 DWORD index, INSTALLSTATE state, BSTR drive,
2746 DWORD *buflen, INT *cost, INT *temp )
2748 msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
2749 UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp);
2750 return HRESULT_FROM_WIN32(r);
2753 static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
2755 mrp_QueryInterface,
2756 mrp_AddRef,
2757 mrp_Release,
2758 mrp_SetMsiHandle,
2759 mrp_GetActiveDatabase,
2760 mrp_GetProperty,
2761 mrp_SetProperty,
2762 mrp_ProcessMessage,
2763 mrp_DoAction,
2764 mrp_Sequence,
2765 mrp_GetTargetPath,
2766 mrp_SetTargetPath,
2767 mrp_GetSourcePath,
2768 mrp_GetMode,
2769 mrp_SetMode,
2770 mrp_GetFeatureState,
2771 mrp_SetFeatureState,
2772 mrp_GetComponentState,
2773 mrp_SetComponentState,
2774 mrp_GetLanguage,
2775 mrp_SetInstallLevel,
2776 mrp_FormatRecord,
2777 mrp_EvaluateCondition,
2778 mrp_GetFeatureCost,
2779 mrp_EnumComponentCosts
2782 HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
2784 msi_remote_package_impl* This;
2786 This = msi_alloc( sizeof *This );
2787 if (!This)
2788 return E_OUTOFMEMORY;
2790 This->IWineMsiRemotePackage_iface.lpVtbl = &msi_remote_package_vtbl;
2791 This->package = 0;
2792 This->refs = 1;
2794 *ppObj = &This->IWineMsiRemotePackage_iface;
2796 return S_OK;
2799 UINT msi_package_add_info(MSIPACKAGE *package, DWORD context, DWORD options,
2800 LPCWSTR property, LPWSTR value)
2802 MSISOURCELISTINFO *info;
2804 LIST_FOR_EACH_ENTRY( info, &package->sourcelist_info, MSISOURCELISTINFO, entry )
2806 if (!strcmpW( info->value, value )) return ERROR_SUCCESS;
2809 info = msi_alloc(sizeof(MSISOURCELISTINFO));
2810 if (!info)
2811 return ERROR_OUTOFMEMORY;
2813 info->context = context;
2814 info->options = options;
2815 info->property = property;
2816 info->value = strdupW(value);
2817 list_add_head(&package->sourcelist_info, &info->entry);
2819 return ERROR_SUCCESS;
2822 UINT msi_package_add_media_disk(MSIPACKAGE *package, DWORD context, DWORD options,
2823 DWORD disk_id, LPWSTR volume_label, LPWSTR disk_prompt)
2825 MSIMEDIADISK *disk;
2827 LIST_FOR_EACH_ENTRY( disk, &package->sourcelist_media, MSIMEDIADISK, entry )
2829 if (disk->disk_id == disk_id) return ERROR_SUCCESS;
2832 disk = msi_alloc(sizeof(MSIMEDIADISK));
2833 if (!disk)
2834 return ERROR_OUTOFMEMORY;
2836 disk->context = context;
2837 disk->options = options;
2838 disk->disk_id = disk_id;
2839 disk->volume_label = strdupW(volume_label);
2840 disk->disk_prompt = strdupW(disk_prompt);
2841 list_add_head(&package->sourcelist_media, &disk->entry);
2843 return ERROR_SUCCESS;