Fix some gcc 4.0 warnings.
[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 /*
259  * Ok my original interpretation of this was wrong. And it looks like msdn has
260  * changed a bit also. The given folder path does not have to actually already
261  * exist, it just cannot be read only and must be a legal folder path.
262  */
263 UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, 
264                              LPCWSTR szFolderPath)
265 {
266     DWORD i;
267     DWORD attrib;
268     LPWSTR path = NULL;
269     LPWSTR path2 = NULL;
270     MSIFOLDER *folder;
271
272     TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
273
274     if (package==NULL)
275         return ERROR_INVALID_HANDLE;
276
277     if (szFolderPath[0]==0)
278         return ERROR_FUNCTION_FAILED;
279
280     attrib = GetFileAttributesW(szFolderPath);
281     if ( attrib != INVALID_FILE_ATTRIBUTES &&
282           (!(attrib & FILE_ATTRIBUTE_DIRECTORY) ||
283            attrib & FILE_ATTRIBUTE_OFFLINE ||
284            attrib & FILE_ATTRIBUTE_READONLY))
285         return ERROR_FUNCTION_FAILED;
286
287     path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
288
289     if (!path)
290         return ERROR_INVALID_PARAMETER;
291
292     if (attrib == INVALID_FILE_ATTRIBUTES)
293     {
294         if (!CreateDirectoryW(szFolderPath,NULL))
295             return ERROR_FUNCTION_FAILED;
296         RemoveDirectoryW(szFolderPath);
297     }
298
299     HeapFree(GetProcessHeap(),0,folder->Property);
300     folder->Property = build_directory_name(2, szFolderPath, NULL);
301
302     if (lstrcmpiW(path, folder->Property) == 0)
303     {
304         /*
305          *  Resolved Target has not really changed, so just 
306          *  set this folder and do not recalculate everything.
307          */
308         HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);
309         folder->ResolvedTarget = NULL;
310         path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
311         HeapFree(GetProcessHeap(),0,path2);
312     }
313     else
314     {
315         for (i = 0; i < package->loaded_folders; i++)
316         {
317             HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget);
318             package->folders[i].ResolvedTarget=NULL;
319         }
320
321         for (i = 0; i < package->loaded_folders; i++)
322         {
323             path2=resolve_folder(package, package->folders[i].Directory, FALSE,
324                        TRUE, NULL);
325             HeapFree(GetProcessHeap(),0,path2);
326         }
327     }
328     HeapFree(GetProcessHeap(),0,path);
329
330     return ERROR_SUCCESS;
331 }
332
333 /***********************************************************************
334  * MsiSetTargetPathW  (MSI.@)
335  */
336 UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, 
337                              LPCWSTR szFolderPath)
338 {
339     MSIPACKAGE *package;
340     UINT ret;
341
342     TRACE("(%s %s)\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
343
344     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
345     ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
346     msiobj_release( &package->hdr );
347     return ret;
348 }
349
350 /***********************************************************************
351  *           MsiGetMode    (MSI.@)
352  *
353  * Returns an internal installer state (if it is running in a mode iRunMode)
354  *
355  * PARAMS
356  *   hInstall    [I]  Handle to the installation
357  *   hRunMode    [I]  Checking run mode
358  *        MSIRUNMODE_ADMIN             Administrative mode
359  *        MSIRUNMODE_ADVERTISE         Advertisement mode
360  *        MSIRUNMODE_MAINTENANCE       Maintenance mode
361  *        MSIRUNMODE_ROLLBACKENABLED   Rollback is enabled
362  *        MSIRUNMODE_LOGENABLED        Log file is writing
363  *        MSIRUNMODE_OPERATIONS        Operations in progress??
364  *        MSIRUNMODE_REBOOTATEND       We need to reboot after installation completed
365  *        MSIRUNMODE_REBOOTNOW         We need to reboot to continue the installation
366  *        MSIRUNMODE_CABINET           Files from cabinet are installed
367  *        MSIRUNMODE_SOURCESHORTNAMES  Long names in source files is suppressed
368  *        MSIRUNMODE_TARGETSHORTNAMES  Long names in destination files is suppressed
369  *        MSIRUNMODE_RESERVED11        Reserved
370  *        MSIRUNMODE_WINDOWS9X         Running under Windows95/98
371  *        MSIRUNMODE_ZAWENABLED        Demand installation is supported
372  *        MSIRUNMODE_RESERVED14        Reserved
373  *        MSIRUNMODE_RESERVED15        Reserved
374  *        MSIRUNMODE_SCHEDULED         called from install script
375  *        MSIRUNMODE_ROLLBACK          called from rollback script
376  *        MSIRUNMODE_COMMIT            called from commit script
377  *
378  * RETURNS
379  *    In the state: TRUE
380  *    Not in the state: FALSE
381  *
382  */
383
384 BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
385 {
386     FIXME("STUB (iRunMode=%i)\n",iRunMode);
387     return TRUE;
388 }
389
390 /***********************************************************************
391  * MsiSetFeatureStateA (MSI.@)
392  *
393  * According to the docs, when this is called it immediately recalculates
394  * all the component states as well
395  */
396 UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
397                                 INSTALLSTATE iState)
398 {
399     LPWSTR szwFeature = NULL;
400     UINT rc;
401
402     szwFeature = strdupAtoW(szFeature);
403
404     if (!szwFeature)
405         return ERROR_FUNCTION_FAILED;
406    
407     rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); 
408
409     HeapFree(GetProcessHeap(),0,szwFeature);
410
411     return rc;
412 }
413
414
415
416 UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
417                                 INSTALLSTATE iState)
418 {
419     INT index, i;
420     UINT rc = ERROR_SUCCESS;
421
422     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
423
424     index = get_loaded_feature(package,szFeature);
425     if (index < 0)
426         return ERROR_UNKNOWN_FEATURE;
427
428     if (iState == INSTALLSTATE_ADVERTISED && 
429         package->features[index].Attributes & 
430             msidbFeatureAttributesDisallowAdvertise)
431         return ERROR_FUNCTION_FAILED;
432
433     package->features[index].ActionRequest= iState;
434     package->features[index].Action= iState;
435
436     ACTION_UpdateComponentStates(package,szFeature);
437
438     /* update all the features that are children of this feature */
439     for (i = 0; i < package->loaded_features; i++)
440     {
441         if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0)
442             MSI_SetFeatureStateW(package, package->features[i].Feature, iState);
443     }
444     
445     return rc;
446 }
447
448 /***********************************************************************
449  * MsiSetFeatureStateW (MSI.@)
450  */
451 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
452                                 INSTALLSTATE iState)
453 {
454     MSIPACKAGE* package;
455     UINT rc = ERROR_SUCCESS;
456
457     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
458
459     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
460     if (!package)
461         return ERROR_INVALID_HANDLE;
462
463     rc = MSI_SetFeatureStateW(package,szFeature,iState);
464
465     msiobj_release( &package->hdr );
466     return rc;
467 }
468
469 /***********************************************************************
470 * MsiGetFeatureStateA   (MSI.@)
471 */
472 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
473                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
474 {
475     LPWSTR szwFeature = NULL;
476     UINT rc;
477     
478     szwFeature = strdupAtoW(szFeature);
479
480     rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
481
482     HeapFree( GetProcessHeap(), 0 , szwFeature);
483
484     return rc;
485 }
486
487 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
488                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
489 {
490     INT index;
491
492     index = get_loaded_feature(package,szFeature);
493     if (index < 0)
494         return ERROR_UNKNOWN_FEATURE;
495
496     if (piInstalled)
497         *piInstalled = package->features[index].Installed;
498
499     if (piAction)
500         *piAction = package->features[index].Action;
501
502     TRACE("returning %i %i\n",*piInstalled,*piAction);
503
504     return ERROR_SUCCESS;
505 }
506
507 /***********************************************************************
508 * MsiGetFeatureStateW   (MSI.@)
509 */
510 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
511                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
512 {
513     MSIPACKAGE* package;
514     UINT ret;
515
516     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
517 piAction);
518
519     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
520     if (!package)
521         return ERROR_INVALID_HANDLE;
522     ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
523     msiobj_release( &package->hdr );
524     return ret;
525 }
526
527 /***********************************************************************
528  * MsiGetComponentStateA (MSI.@)
529  */
530 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
531                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
532 {
533     LPWSTR szwComponent= NULL;
534     UINT rc;
535     
536     szwComponent= strdupAtoW(szComponent);
537
538     rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
539
540     HeapFree( GetProcessHeap(), 0 , szwComponent);
541
542     return rc;
543 }
544
545 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
546                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
547 {
548     MSICOMPONENT *comp;
549
550     TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
551 piAction);
552
553     comp = get_loaded_component(package,szComponent);
554     if (!comp)
555         return ERROR_UNKNOWN_COMPONENT;
556
557     if (piInstalled)
558         *piInstalled = comp->Installed;
559
560     if (piAction)
561         *piAction = comp->Action;
562
563     TRACE("states (%i, %i)\n",
564 (piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
565
566     return ERROR_SUCCESS;
567 }
568
569 /***********************************************************************
570  * MsiGetComponentStateW (MSI.@)
571  */
572 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
573                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
574 {
575     MSIPACKAGE* package;
576     UINT ret;
577
578     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
579            piInstalled, piAction);
580
581     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
582     if (!package)
583         return ERROR_INVALID_HANDLE;
584     ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
585     msiobj_release( &package->hdr );
586     return ret;
587 }
588
589 /***********************************************************************
590  * MsiGetLanguage (MSI.@)
591  */
592 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
593 {
594     MSIPACKAGE* package;
595     LANGID langid;
596     LPWSTR buffer;
597     static const WCHAR szProductLanguage[] =
598         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
599     
600     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
601     if (!package)
602         return ERROR_INVALID_HANDLE;
603
604     buffer = load_dynamic_property(package,szProductLanguage,NULL);
605     langid = atoiW(buffer);
606
607     HeapFree(GetProcessHeap(),0,buffer);
608     msiobj_release (&package->hdr);
609     return langid;
610 }