Moved mciavi32 to the top-level dlls directory.
[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 attrib;
267     LPWSTR path = NULL;
268     LPWSTR path2 = NULL;
269     MSIFOLDER *folder;
270
271     TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
272
273     if (package==NULL)
274         return ERROR_INVALID_HANDLE;
275
276     if (szFolderPath[0]==0)
277         return ERROR_FUNCTION_FAILED;
278
279     attrib = GetFileAttributesW(szFolderPath);
280     if ( attrib != INVALID_FILE_ATTRIBUTES &&
281           (!(attrib & FILE_ATTRIBUTE_DIRECTORY) ||
282            attrib & FILE_ATTRIBUTE_OFFLINE ||
283            attrib & FILE_ATTRIBUTE_READONLY))
284         return ERROR_FUNCTION_FAILED;
285
286     path = resolve_folder(package,szFolder,FALSE,FALSE,&folder);
287
288     if (!path)
289         return ERROR_INVALID_PARAMETER;
290
291     if (attrib == INVALID_FILE_ATTRIBUTES)
292     {
293         if (!CreateDirectoryW(szFolderPath,NULL))
294             return ERROR_FUNCTION_FAILED;
295         RemoveDirectoryW(szFolderPath);
296     }
297
298     HeapFree(GetProcessHeap(),0,folder->Property);
299     folder->Property = build_directory_name(2, szFolderPath, NULL);
300
301     if (lstrcmpiW(path, folder->Property) == 0)
302     {
303         /*
304          *  Resolved Target has not really changed, so just 
305          *  set this folder and do not recalculate everything.
306          */
307         HeapFree(GetProcessHeap(),0,folder->ResolvedTarget);
308         folder->ResolvedTarget = NULL;
309         path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL);
310         HeapFree(GetProcessHeap(),0,path2);
311     }
312     else
313     {
314         MSIFOLDER *f;
315
316         LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
317         {
318             HeapFree( GetProcessHeap(),0,f->ResolvedTarget);
319             f->ResolvedTarget=NULL;
320         }
321
322         LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
323         {
324             path2 = resolve_folder(package, f->Directory, FALSE, 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     UINT rc = ERROR_SUCCESS;
420     MSIFEATURE *feature, *child;
421
422     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
423
424     feature = get_loaded_feature(package,szFeature);
425     if (!feature)
426         return ERROR_UNKNOWN_FEATURE;
427
428     if (iState == INSTALLSTATE_ADVERTISED && 
429         feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
430         return ERROR_FUNCTION_FAILED;
431
432     feature->ActionRequest = iState;
433     feature->Action = iState;
434
435     ACTION_UpdateComponentStates(package,szFeature);
436
437     /* update all the features that are children of this feature */
438     LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
439     {
440         if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
441             MSI_SetFeatureStateW(package, child->Feature, iState);
442     }
443     
444     return rc;
445 }
446
447 /***********************************************************************
448  * MsiSetFeatureStateW (MSI.@)
449  */
450 UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
451                                 INSTALLSTATE iState)
452 {
453     MSIPACKAGE* package;
454     UINT rc = ERROR_SUCCESS;
455
456     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
457
458     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
459     if (!package)
460         return ERROR_INVALID_HANDLE;
461
462     rc = MSI_SetFeatureStateW(package,szFeature,iState);
463
464     msiobj_release( &package->hdr );
465     return rc;
466 }
467
468 /***********************************************************************
469 * MsiGetFeatureStateA   (MSI.@)
470 */
471 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
472                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
473 {
474     LPWSTR szwFeature = NULL;
475     UINT rc;
476     
477     szwFeature = strdupAtoW(szFeature);
478
479     rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);
480
481     HeapFree( GetProcessHeap(), 0 , szwFeature);
482
483     return rc;
484 }
485
486 UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
487                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
488 {
489     MSIFEATURE *feature;
490
491     feature = get_loaded_feature(package,szFeature);
492     if (!feature)
493         return ERROR_UNKNOWN_FEATURE;
494
495     if (piInstalled)
496         *piInstalled = feature->Installed;
497
498     if (piAction)
499         *piAction = feature->Action;
500
501     TRACE("returning %i %i\n", feature->Installed, feature->Action);
502
503     return ERROR_SUCCESS;
504 }
505
506 /***********************************************************************
507 * MsiGetFeatureStateW   (MSI.@)
508 */
509 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
510                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
511 {
512     MSIPACKAGE* package;
513     UINT ret;
514
515     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled,
516 piAction);
517
518     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
519     if (!package)
520         return ERROR_INVALID_HANDLE;
521     ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
522     msiobj_release( &package->hdr );
523     return ret;
524 }
525
526 /***********************************************************************
527  * MsiGetComponentStateA (MSI.@)
528  */
529 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szComponent,
530                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
531 {
532     LPWSTR szwComponent= NULL;
533     UINT rc;
534     
535     szwComponent= strdupAtoW(szComponent);
536
537     rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);
538
539     HeapFree( GetProcessHeap(), 0 , szwComponent);
540
541     return rc;
542 }
543
544 UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
545                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
546 {
547     MSICOMPONENT *comp;
548
549     TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
550            piInstalled, piAction);
551
552     comp = get_loaded_component(package,szComponent);
553     if (!comp)
554         return ERROR_UNKNOWN_COMPONENT;
555
556     if (piInstalled)
557         *piInstalled = comp->Installed;
558
559     if (piAction)
560         *piAction = comp->Action;
561
562     TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
563
564     return ERROR_SUCCESS;
565 }
566
567 /***********************************************************************
568  * MsiGetComponentStateW (MSI.@)
569  */
570 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szComponent,
571                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
572 {
573     MSIPACKAGE* package;
574     UINT ret;
575
576     TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
577            piInstalled, piAction);
578
579     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
580     if (!package)
581         return ERROR_INVALID_HANDLE;
582     ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
583     msiobj_release( &package->hdr );
584     return ret;
585 }
586
587 /***********************************************************************
588  * MsiGetLanguage (MSI.@)
589  */
590 LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
591 {
592     MSIPACKAGE* package;
593     LANGID langid;
594     LPWSTR buffer;
595     static const WCHAR szProductLanguage[] =
596         {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
597     
598     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
599     if (!package)
600         return ERROR_INVALID_HANDLE;
601
602     buffer = load_dynamic_property(package,szProductLanguage,NULL);
603     langid = atoiW(buffer);
604
605     HeapFree(GetProcessHeap(),0,buffer);
606     msiobj_release (&package->hdr);
607     return langid;
608 }