Break out all the top level apis into install.c.
[wine] / dlls / msi / install.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /* Msi top level apis directly related to installs */
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wine/debug.h"
29 #include "msi.h"
30 #include "msidefs.h"
31 #include "msipriv.h"
32 #include "winuser.h"
33 #include "wine/unicode.h"
34 #include "action.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37
38 /***********************************************************************
39  * MsiDoActionA       (MSI.@)
40  */
41 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
42 {
43     LPWSTR szwAction;
44     UINT rc;
45
46     TRACE(" exteral attempt at action %s\n",szAction);
47
48     if (!szAction)
49         return ERROR_FUNCTION_FAILED;
50     if (hInstall == 0)
51         return ERROR_FUNCTION_FAILED;
52
53     szwAction = strdupAtoW(szAction);
54
55     if (!szwAction)
56         return ERROR_FUNCTION_FAILED; 
57
58
59     rc = MsiDoActionW(hInstall, szwAction);
60     HeapFree(GetProcessHeap(),0,szwAction);
61     return rc;
62 }
63
64 /***********************************************************************
65  * MsiDoActionW       (MSI.@)
66  */
67 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
68 {
69     MSIPACKAGE *package;
70     UINT ret = ERROR_INVALID_HANDLE;
71
72     TRACE(" external attempt at action %s \n",debugstr_w(szAction));
73
74     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
75     if( package )
76     {
77         ret = ACTION_PerformUIAction(package,szAction);
78         msiobj_release( &package->hdr );
79     }
80     return ret;
81 }
82
83 /***********************************************************************
84  * MsiGetTargetPathA        (MSI.@)
85  */
86 UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 
87                                LPSTR szPathBuf, DWORD* pcchPathBuf) 
88 {
89     LPWSTR szwFolder;
90     LPWSTR szwPathBuf;
91     UINT rc;
92
93     TRACE("getting folder %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
94
95     if (!szFolder)
96         return ERROR_FUNCTION_FAILED;
97     if (hInstall == 0)
98         return ERROR_FUNCTION_FAILED;
99
100     szwFolder = strdupAtoW(szFolder);
101
102     if (!szwFolder)
103         return ERROR_FUNCTION_FAILED; 
104
105     szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
106
107     rc = MsiGetTargetPathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
108
109     WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
110                          *pcchPathBuf, NULL, NULL );
111
112     HeapFree(GetProcessHeap(),0,szwFolder);
113     HeapFree(GetProcessHeap(),0,szwPathBuf);
114
115     return rc;
116 }
117
118 /***********************************************************************
119 * MsiGetTargetPathW        (MSI.@)
120 */
121 UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
122                                 szPathBuf, DWORD* pcchPathBuf) 
123 {
124     LPWSTR path;
125     UINT rc = ERROR_FUNCTION_FAILED;
126     MSIPACKAGE *package;
127
128     TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
129
130     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
131     if (!package)
132         return ERROR_INVALID_HANDLE;
133     path = resolve_folder(package, szFolder, FALSE, FALSE, NULL);
134     msiobj_release( &package->hdr );
135
136     if (path && (strlenW(path) > *pcchPathBuf))
137     {
138         *pcchPathBuf = strlenW(path)+1;
139         rc = ERROR_MORE_DATA;
140     }
141     else if (path)
142     {
143         *pcchPathBuf = strlenW(path)+1;
144         strcpyW(szPathBuf,path);
145         TRACE("Returning Path %s\n",debugstr_w(path));
146         rc = ERROR_SUCCESS;
147     }
148     HeapFree(GetProcessHeap(),0,path);
149     
150     return rc;
151 }
152
153
154 /***********************************************************************
155 * MsiGetSourcePathA     (MSI.@)
156 */
157 UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, 
158                                LPSTR szPathBuf, DWORD* pcchPathBuf) 
159 {
160     LPWSTR szwFolder;
161     LPWSTR szwPathBuf;
162     UINT rc;
163
164     TRACE("getting source %s %p %li\n",szFolder,szPathBuf, *pcchPathBuf);
165
166     if (!szFolder)
167         return ERROR_FUNCTION_FAILED;
168     if (hInstall == 0)
169         return ERROR_FUNCTION_FAILED;
170
171     szwFolder = strdupAtoW(szFolder);
172     if (!szwFolder)
173         return ERROR_FUNCTION_FAILED; 
174
175     szwPathBuf = HeapAlloc( GetProcessHeap(), 0 , *pcchPathBuf * sizeof(WCHAR));
176
177     rc = MsiGetSourcePathW(hInstall, szwFolder, szwPathBuf,pcchPathBuf);
178
179     WideCharToMultiByte( CP_ACP, 0, szwPathBuf, *pcchPathBuf, szPathBuf,
180                          *pcchPathBuf, NULL, NULL );
181
182     HeapFree(GetProcessHeap(),0,szwFolder);
183     HeapFree(GetProcessHeap(),0,szwPathBuf);
184
185     return rc;
186 }
187
188 /***********************************************************************
189 * MsiGetSourcePathW     (MSI.@)
190 */
191 UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR
192                                 szPathBuf, DWORD* pcchPathBuf) 
193 {
194     LPWSTR path;
195     UINT rc = ERROR_FUNCTION_FAILED;
196     MSIPACKAGE *package;
197
198     TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf);
199
200     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
201     if( !package )
202         return ERROR_INVALID_HANDLE;
203     path = resolve_folder(package, szFolder, TRUE, FALSE, NULL);
204     msiobj_release( &package->hdr );
205
206     if (path && strlenW(path) > *pcchPathBuf)
207     {
208         *pcchPathBuf = strlenW(path)+1;
209         rc = ERROR_MORE_DATA;
210     }
211     else if (path)
212     {
213         *pcchPathBuf = strlenW(path)+1;
214         strcpyW(szPathBuf,path);
215         TRACE("Returning Path %s\n",debugstr_w(path));
216         rc = ERROR_SUCCESS;
217     }
218     HeapFree(GetProcessHeap(),0,path);
219     
220     return rc;
221 }
222
223
224 /***********************************************************************
225  * MsiSetTargetPathA  (MSI.@)
226  */
227 UINT WINAPI MsiSetTargetPathA(MSIHANDLE hInstall, LPCSTR szFolder, 
228                              LPCSTR szFolderPath)
229 {
230     LPWSTR szwFolder;
231     LPWSTR szwFolderPath;
232     UINT rc;
233
234     if (!szFolder)
235         return ERROR_FUNCTION_FAILED;
236     if (hInstall == 0)
237         return ERROR_FUNCTION_FAILED;
238
239     szwFolder = strdupAtoW(szFolder);
240     if (!szwFolder)
241         return ERROR_FUNCTION_FAILED; 
242
243     szwFolderPath = strdupAtoW(szFolderPath);
244     if (!szwFolderPath)
245     {
246         HeapFree(GetProcessHeap(),0,szwFolder);
247         return ERROR_FUNCTION_FAILED; 
248     }
249
250     rc = MsiSetTargetPathW(hInstall, szwFolder, szwFolderPath);
251
252     HeapFree(GetProcessHeap(),0,szwFolder);
253     HeapFree(GetProcessHeap(),0,szwFolderPath);
254
255     return rc;
256 }
257
258 UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, 
259                              LPCWSTR szFolderPath)
260 {
261     DWORD i;
262     LPWSTR path = NULL;
263     LPWSTR path2 = NULL;
264     MSIFOLDER *folder;
265
266     TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
267
268     if (package==NULL)
269         return ERROR_INVALID_HANDLE;
270
271     if (szFolderPath[0]==0)
272         return ERROR_FUNCTION_FAILED;
273
274     if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES)
275         return ERROR_FUNCTION_FAILED;
276
277     path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
278
279     if (!path)
280         return ERROR_INVALID_PARAMETER;
281
282     HeapFree(GetProcessHeap(),0,folder->Property);
283     folder->Property = build_directory_name(2, szFolderPath, NULL);
284
285     if (lstrcmpiW(path, folder->Property) == 0)
286     {
287         /*
288          *  Resolved Target has not really changed, so just 
289          *  set this folder and do not recalculate everything.
290          */
291         HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);
292         folder->ResolvedTarget = NULL;
293         path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
294         HeapFree(GetProcessHeap(),0,path2);
295     }
296     else
297     {
298         for (i = 0; i < package->loaded_folders; i++)
299         {
300             HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
301             package->folders[i].ResolvedTarget=NULL;
302         }
303
304         for (i = 0; i < package->loaded_folders; i++)
305         {
306             path2=resolve_folder(package, package->folders[i].Directory, FALSE,
307                        TRUE, NULL);
308             HeapFree(GetProcessHeap(),0,path2);
309         }
310     }
311     HeapFree(GetProcessHeap(),0,path);
312
313     return ERROR_SUCCESS;
314 }
315
316 /***********************************************************************
317  * MsiSetTargetPathW  (MSI.@)
318  */
319 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, 
320                              LPCWSTR szFolderPath)
321 {
322     MSIPACKAGE *package;
323     UINT ret;
324
325     TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
326
327     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
328     ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
329     msiobj_release( &package->hdr );
330     return ret;
331 }
332
333 /***********************************************************************
334  *           MsiGetMode    (MSI.@)
335  *
336  * Returns an internal installer state (if it is running in a mode iRunMode)
337  *
338  * PARAMS
339  *   hInstall    [I]  Handle to the installation
340  *   hRunMode    [I]  Checking run mode
341  *        MSIRUNMODE_ADMIN             Administrative mode
342  *        MSIRUNMODE_ADVERTISE         Advertisement mode
343  *        MSIRUNMODE_MAINTENANCE       Maintenance mode
344  *        MSIRUNMODE_ROLLBACKENABLED   Rollback is enabled
345  *        MSIRUNMODE_LOGENABLED        Log file is writing
346  *        MSIRUNMODE_OPERATIONS        Operations in progress??
347  *        MSIRUNMODE_REBOOTATEND       We need to reboot after installation completed
348  *        MSIRUNMODE_REBOOTNOW         We need to reboot to continue the installation
349  *        MSIRUNMODE_CABINET           Files from cabinet are installed
350  *        MSIRUNMODE_SOURCESHORTNAMES  Long names in source files is suppressed
351  *        MSIRUNMODE_TARGETSHORTNAMES  Long names in destination files is suppressed
352  *        MSIRUNMODE_RESERVED11        Reserved
353  *        MSIRUNMODE_WINDOWS9X         Running under Windows95/98
354  *        MSIRUNMODE_ZAWENABLED        Demand installation is supported
355  *        MSIRUNMODE_RESERVED14        Reserved
356  *        MSIRUNMODE_RESERVED15        Reserved
357  *        MSIRUNMODE_SCHEDULED         called from install script
358  *        MSIRUNMODE_ROLLBACK          called from rollback script
359  *        MSIRUNMODE_COMMIT            called from commit script
360  *
361  * RETURNS
362  *    In the state: TRUE
363  *    Not in the state: FALSE
364  *
365  */
366
367 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
368 {
369     FIXME("STUB (iRunMode=%i)\n",iRunMode);
370     return TRUE;
371 }
372
373 /***********************************************************************
374  * MsiSetFeatureStateA (MSI.@)
375  *
376  * According to the docs, when this is called it immediately recalculates
377  * all the component states as well
378  */
379 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
380                                 INSTALLSTATE iState)
381 {
382     LPWSTR szwFeature = NULL;
383     UINT rc;
384
385     szwFeature = strdupAtoW(szFeature);
386
387     if (!szwFeature)
388         return ERROR_FUNCTION_FAILED;
389    
390     rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); 
391
392     HeapFree(GetProcessHeap(),0,szwFeature);
393
394     return rc;
395 }
396
397
398
399 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
400                                 INSTALLSTATE iState)
401 {
402     INT index, i;
403     UINT rc = ERROR_SUCCESS;
404
405     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
406
407     index = get_loaded_feature(package,szFeature);
408     if (index < 0)
409         return ERROR_UNKNOWN_FEATURE;
410
411     if (iState == INSTALLSTATE_ADVERTISED && 
412         package->features[index].Attributes & 
413             msidbFeatureAttributesDisallowAdvertise)
414         return ERROR_FUNCTION_FAILED;
415
416     package->features[index].ActionRequest= iState;
417     package->features[index].Action= iState;
418
419     ACTION_UpdateComponentStates(package,szFeature);
420
421     /* update all the features that are children of this feature */
422     for (i = 0; i < package->loaded_features; i++)
423     {
424         if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0)
425             MSI_SetFeatureStateW(package, package->features[i].Feature, iState);
426     }
427     
428     return rc;
429 }
430
431 /***********************************************************************
432  * MsiSetFeatureStateW (MSI.@)
433  */
434 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
435                                 INSTALLSTATE iState)
436 {
437     MSIPACKAGE* package;
438     UINT rc = ERROR_SUCCESS;
439
440     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
441
442     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
443     if (!package)
444         return ERROR_INVALID_HANDLE;
445
446     rc = MSI_SetFeatureStateW(package,szFeature,iState);
447
448     msiobj_release( &package->hdr );
449     return rc;
450 }
451
452 /***********************************************************************
453 * MsiGetFeatureStateA   (MSI.@)
454 */
455 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
456                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
457 {
458     LPWSTR szwFeature = NULL;
459     UINT rc;
460     
461     szwFeature = strdupAtoW(szFeature);
462
463     rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
464
465     HeapFree( GetProcessHeap(), 0 , szwFeature);
466
467     return rc;
468 }
469
470 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
471                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
472 {
473     INT index;
474
475     index = get_loaded_feature(package,szFeature);
476     if (index < 0)
477         return ERROR_UNKNOWN_FEATURE;
478
479     if (piInstalled)
480         *piInstalled = package->features[index].Installed;
481
482     if (piAction)
483         *piAction = package->features[index].Action;
484
485     TRACE("returning %i %i\n",*piInstalled,*piAction);
486
487     return ERROR_SUCCESS;
488 }
489
490 /***********************************************************************
491 * MsiGetFeatureStateW   (MSI.@)
492 */
493 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
494                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
495 {
496     MSIPACKAGE* package;
497     UINT ret;
498
499     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
500 piAction);
501
502     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
503     if (!package)
504         return ERROR_INVALID_HANDLE;
505     ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
506     msiobj_release( &package->hdr );
507     return ret;
508 }
509
510 /***********************************************************************
511  * MsiGetComponentStateA (MSI.@)
512  */
513 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
514                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
515 {
516     LPWSTR szwComponent= NULL;
517     UINT rc;
518     
519     szwComponent= strdupAtoW(szComponent);
520
521     rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
522
523     HeapFree( GetProcessHeap(), 0 , szwComponent);
524
525     return rc;
526 }
527
528 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
529                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
530 {
531     INT index;
532
533     TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
534 piAction);
535
536     index = get_loaded_component(package,szComponent);
537     if (index < 0)
538         return ERROR_UNKNOWN_COMPONENT;
539
540     if (piInstalled)
541         *piInstalled = package->components[index].Installed;
542
543     if (piAction)
544         *piAction = package->components[index].Action;
545
546     TRACE("states (%i, %i)\n",
547 (piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
548
549     return ERROR_SUCCESS;
550 }
551
552 /***********************************************************************
553  * MsiGetComponentStateW (MSI.@)
554  */
555 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
556                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
557 {
558     MSIPACKAGE* package;
559     UINT ret;
560
561     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
562            piInstalled, piAction);
563
564     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
565     if (!package)
566         return ERROR_INVALID_HANDLE;
567     ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
568     msiobj_release( &package->hdr );
569     return ret;
570 }