msi: Update controls based on a property when that property changes.
[wine] / dlls / msi / preview.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 Mike McCormack 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 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "msi.h"
29 #include "msipriv.h"
30 #include "msiserver.h"
31
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(msi);
36
37 static void MSI_ClosePreview( MSIOBJECTHDR *arg )
38 {
39     MSIPREVIEW *preview = (MSIPREVIEW *) arg;
40
41     msiobj_release( &preview->package->hdr );
42 }
43
44 MSIPREVIEW *MSI_EnableUIPreview( MSIDATABASE *db )
45 {
46     MSIPREVIEW *preview = NULL;
47     MSIPACKAGE *package;
48
49     package = MSI_CreatePackage( db, NULL );
50     if( package )
51     {
52         preview = alloc_msiobject( MSIHANDLETYPE_PREVIEW, sizeof (MSIPREVIEW),
53                                MSI_ClosePreview );
54         if( preview )
55         {
56             preview->package = package;
57             preview->dialog = 0;
58             msiobj_addref( &package->hdr );
59         }
60         msiobj_release( &package->hdr );
61     }
62     return preview;
63 }
64
65 UINT WINAPI MsiEnableUIPreview( MSIHANDLE hdb, MSIHANDLE* phPreview )
66 {
67     MSIDATABASE *db;
68     MSIPREVIEW *preview;
69     UINT r = ERROR_FUNCTION_FAILED;
70
71     TRACE("%ld %p\n", hdb, phPreview);
72
73     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
74     if( !db )
75     {
76         IWineMsiRemoteDatabase *remote_database;
77
78         remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hdb );
79         if ( !remote_database )
80             return ERROR_INVALID_HANDLE;
81
82         *phPreview = 0;
83
84         IWineMsiRemoteDatabase_Release( remote_database );
85         WARN("MsiEnableUIPreview not allowed during a custom action!\n");
86
87         return ERROR_FUNCTION_FAILED;
88     }
89
90     preview = MSI_EnableUIPreview( db );
91     if( preview )
92     {
93         *phPreview = alloc_msihandle( &preview->hdr );
94         msiobj_release( &preview->hdr );
95         r = ERROR_SUCCESS;
96         if (! *phPreview)
97             r = ERROR_NOT_ENOUGH_MEMORY;
98     }
99     msiobj_release( &db->hdr );
100
101     return r;
102 }
103
104 static UINT preview_event_handler( MSIPACKAGE *package, LPCWSTR event,
105                                    LPCWSTR argument, msi_dialog *dialog )
106 {
107     MESSAGE("Preview dialog event '%s' (arg='%s')\n",
108             debugstr_w( event ), debugstr_w( argument ));
109     return ERROR_SUCCESS;
110 }
111
112 UINT MSI_PreviewDialogW( MSIPREVIEW *preview, LPCWSTR szDialogName )
113 {
114     msi_dialog *dialog = NULL;
115     UINT r = ERROR_SUCCESS;
116
117     if( preview->dialog )
118         msi_dialog_destroy( preview->dialog );
119
120     /* an empty name means we should just destroy the current preview dialog */
121     if( szDialogName )
122     {
123         dialog = msi_dialog_create( preview->package, szDialogName, NULL,
124                                     preview_event_handler );
125         if( dialog )
126             msi_dialog_do_preview( dialog );
127         else
128             r = ERROR_FUNCTION_FAILED;
129     }
130     preview->dialog = dialog;
131
132     return r;
133 }
134
135 UINT WINAPI MsiPreviewDialogW( MSIHANDLE hPreview, LPCWSTR szDialogName )
136 {
137     MSIPREVIEW *preview;
138     UINT r;
139
140     TRACE("%ld %s\n", hPreview, debugstr_w(szDialogName));
141
142     preview = msihandle2msiinfo( hPreview, MSIHANDLETYPE_PREVIEW );
143     if( !preview )
144         return ERROR_INVALID_HANDLE;
145
146     r = MSI_PreviewDialogW( preview, szDialogName );
147
148     msiobj_release( &preview->hdr );
149
150     return r;
151 }
152
153 UINT WINAPI MsiPreviewDialogA( MSIHANDLE hPreview, LPCSTR szDialogName )
154 {
155     UINT r;
156     LPWSTR strW = NULL;
157
158     TRACE("%ld %s\n", hPreview, debugstr_a(szDialogName));
159
160     if( szDialogName )
161     {
162         strW = strdupAtoW( szDialogName );
163         if( !strW )
164             return ERROR_OUTOFMEMORY;
165     }
166     r = MsiPreviewDialogW( hPreview, strW );
167     msi_free( strW );
168     return r;
169 }
170
171 UINT WINAPI MsiPreviewBillboardW( MSIHANDLE hPreview, LPCWSTR szControlName,
172                                   LPCWSTR szBillboard)
173 {
174     FIXME("%ld %s %s\n", hPreview, debugstr_w(szControlName),
175           debugstr_w(szBillboard));
176     return ERROR_CALL_NOT_IMPLEMENTED;
177 }
178
179 UINT WINAPI MsiPreviewBillboardA( MSIHANDLE hPreview, LPCSTR szControlName,
180                                   LPCSTR szBillboard)
181 {
182     FIXME("%ld %s %s\n", hPreview, debugstr_a(szControlName),
183           debugstr_a(szBillboard));
184     return ERROR_CALL_NOT_IMPLEMENTED;
185 }