Implement SetTargetPath, start the basics for tracking UI level.
[wine/multimedia.git] / dlls / msi / package.c
blobc6ee8790a03d232ea0a17b6042499b1863b8da72
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winnls.h"
29 #include "shlwapi.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "msiquery.h"
33 #include "msipriv.h"
34 #include "objidl.h"
35 #include "wincrypt.h"
36 #include "winuser.h"
37 #include "shlobj.h"
38 #include "wine/unicode.h"
39 #include "objbase.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 * The MSVC headers define the MSIDBOPEN_* macros cast to LPCTSTR,
45 * which is a problem because LPCTSTR isn't defined when compiling wine.
46 * To work around this problem, we need to define LPCTSTR as LPCWSTR here,
47 * and make sure to only use it in W functions.
49 #define LPCTSTR LPCWSTR
51 void MSI_FreePackage( VOID *arg);
53 typedef struct tagMSIPACKAGE
55 MSIHANDLE db;
56 } MSIPACKAGE;
58 void MSI_FreePackage( VOID *arg)
60 MSIPACKAGE *package= arg;
62 MsiCloseHandle(package->db);
65 UINT WINAPI MsiOpenPackageA(LPCSTR szPackage, MSIHANDLE *phPackage)
67 LPWSTR szwPack = NULL;
68 UINT len, ret;
70 TRACE("%s %p\n",debugstr_a(szPackage), phPackage);
72 if( szPackage )
74 len = MultiByteToWideChar( CP_ACP, 0, szPackage, -1, NULL, 0 );
75 szwPack = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
76 if( szwPack )
77 MultiByteToWideChar( CP_ACP, 0, szPackage, -1, szwPack, len );
80 ret = MsiOpenPackageW( szwPack, phPackage );
82 if( szwPack )
83 HeapFree( GetProcessHeap(), 0, szwPack );
85 return ret;
89 static const void clone_properties(MSIHANDLE db)
91 MSIHANDLE view;
92 UINT rc;
93 static const CHAR CreateSql[] = "CREATE TABLE `_Property` ( `_Property` "
94 "CHAR(56) NOT NULL, `Value` CHAR(98) NOT NULL PRIMARY KEY `_Property`)";
95 static const CHAR Query[] = "SELECT * from Property";
96 static const CHAR Insert[] =
97 "INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
99 /* create the temporary properties table */
100 MsiDatabaseOpenViewA(db, CreateSql, &view);
101 MsiViewExecute(view,0);
102 MsiViewClose(view);
103 MsiCloseHandle(view);
105 /* clone the existing properties */
106 MsiDatabaseOpenViewA(db, Query, &view);
108 MsiViewExecute(view, 0);
109 while (1)
111 MSIHANDLE row;
112 MSIHANDLE view2;
114 rc = MsiViewFetch(view,&row);
115 if (rc != ERROR_SUCCESS)
116 break;
118 MsiDatabaseOpenViewA(db,Insert,&view2);
119 MsiViewExecute(view2,row);
120 MsiViewClose(view2);
121 MsiCloseHandle(view2);
123 MsiCloseHandle(row);
125 MsiViewClose(view);
126 MsiCloseHandle(view);
131 * There are a whole slew of these we need to set
134 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/properties.asp
136 static VOID set_installer_properties(MSIHANDLE hPackage)
138 WCHAR pth[MAX_PATH];
140 static const WCHAR cszbs[]={'\\',0};
141 static const WCHAR CFF[] =
142 {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
143 static const WCHAR PFF[] =
144 {'P','r','o','g','r','a','m','F','i','l','e','s','F','o','l','d','e','r',0};
145 static const WCHAR CADF[] =
146 {'C','o','m','m','o','n','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
147 static const WCHAR ATF[] =
148 {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
149 static const WCHAR ADF[] =
150 {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
151 static const WCHAR SF[] =
152 {'S','y','s','t','e','m','F','o','l','d','e','r',0};
153 static const WCHAR LADF[] =
154 {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
155 static const WCHAR MPF[] =
156 {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
157 static const WCHAR PF[] =
158 {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
159 static const WCHAR WF[] =
160 {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
161 static const WCHAR TF[]=
162 {'T','e','m','p','F','o','l','d','e','r',0};
164 /* Not yet set ... but needed by iTunes
166 DesktopFolder
167 FavoritesFolder
168 FontsFolder
169 PrimaryVolumePath
170 ProgramFiles64Folder
171 ProgramMenuFolder
172 SendToFolder
173 StartMenuFolder
174 StartupFolder
175 System16Folder
176 System64Folder
177 TemplateFolder
180 /* asked for by iTunes ... but are they installer set?
182 * GlobalAssemblyCache
186 * Other things i notice set
188 ScreenY
189 ScreenX
190 SystemLanguageID
191 ComputerName
192 UserLanguageID
193 LogonUser
194 VirtualMemory
195 PhysicalMemory
196 Intel
197 ShellAdvSupport
198 ServicePackLevel
199 WindowsBuild
200 Version9x
201 Version95
202 VersionNT
203 AdminUser
204 DefaultUIFont
205 VersionMsi
206 VersionDatabase
207 PackagecodeChanging
208 ProductState
209 CaptionHeight
210 BorderTop
211 BorderSide
212 TextHeight
213 ColorBits
214 RedirectedDllSupport
215 Time
216 Date
217 Privilaged
220 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES_COMMON,NULL,0,pth);
221 strcatW(pth,cszbs);
222 MsiSetPropertyW(hPackage, CFF, pth);
224 SHGetFolderPathW(NULL,CSIDL_PROGRAM_FILES,NULL,0,pth);
225 strcatW(pth,cszbs);
226 MsiSetPropertyW(hPackage, PFF, pth);
228 SHGetFolderPathW(NULL,CSIDL_COMMON_APPDATA,NULL,0,pth);
229 strcatW(pth,cszbs);
230 MsiSetPropertyW(hPackage, CADF, pth);
232 SHGetFolderPathW(NULL,CSIDL_ADMINTOOLS,NULL,0,pth);
233 strcatW(pth,cszbs);
234 MsiSetPropertyW(hPackage, ATF, pth);
236 SHGetFolderPathW(NULL,CSIDL_APPDATA,NULL,0,pth);
237 strcatW(pth,cszbs);
238 MsiSetPropertyW(hPackage, ADF, pth);
240 SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth);
241 strcatW(pth,cszbs);
242 MsiSetPropertyW(hPackage, SF, pth);
244 SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth);
245 strcatW(pth,cszbs);
246 MsiSetPropertyW(hPackage, LADF, pth);
248 SHGetFolderPathW(NULL,CSIDL_MYPICTURES,NULL,0,pth);
249 strcatW(pth,cszbs);
250 MsiSetPropertyW(hPackage, MPF, pth);
252 SHGetFolderPathW(NULL,CSIDL_PERSONAL,NULL,0,pth);
253 strcatW(pth,cszbs);
254 MsiSetPropertyW(hPackage, PF, pth);
256 SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth);
257 strcatW(pth,cszbs);
258 MsiSetPropertyW(hPackage, WF, pth);
260 GetTempPathW(MAX_PATH,pth);
261 MsiSetPropertyW(hPackage, TF, pth);
265 UINT WINAPI MsiOpenPackageW(LPCWSTR szPackage, MSIHANDLE *phPackage)
267 UINT rc;
268 MSIHANDLE handle;
269 MSIHANDLE db;
270 MSIPACKAGE *package;
271 CHAR uilevel[10];
273 static const WCHAR OriginalDatabase[] =
274 {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
275 static const WCHAR Database[] =
276 {'D','A','T','A','B','A','S','E',0};
278 TRACE("%s %p\n",debugstr_w(szPackage), phPackage);
280 rc = MsiOpenDatabaseW(szPackage, MSIDBOPEN_READONLY, &db);
282 if (rc != ERROR_SUCCESS)
283 return ERROR_FUNCTION_FAILED;
285 handle = alloc_msihandle(MSIHANDLETYPE_PACKAGE, sizeof (MSIPACKAGE),
286 MSI_FreePackage, (void**)&package);
288 if (!handle)
290 MsiCloseHandle(db);
291 return ERROR_FUNCTION_FAILED;
294 package->db = db;
296 /* ok here is where we do a slew of things to the database to
297 * prep for all that is to come as a package */
299 clone_properties(db);
300 set_installer_properties(handle);
301 MsiSetPropertyW(handle, OriginalDatabase, szPackage);
302 MsiSetPropertyW(handle, Database, szPackage);
303 sprintf(uilevel,"%i",gUILevel);
304 MsiSetPropertyA(handle, "UILevel", uilevel);
306 *phPackage = handle;
308 return ERROR_SUCCESS;
311 UINT WINAPI MsiOpenPackageExA(LPCSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
313 FIXME("%s 0x%08lx %p\n",debugstr_a(szPackage), dwOptions, phPackage);
314 return ERROR_CALL_NOT_IMPLEMENTED;
317 UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phPackage)
319 FIXME("%s 0x%08lx %p\n",debugstr_w(szPackage), dwOptions, phPackage);
320 return ERROR_CALL_NOT_IMPLEMENTED;
323 MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
325 MSIPACKAGE *package;
327 TRACE("(%ld)\n",hInstall);
329 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
331 if( !package)
332 return ERROR_INVALID_HANDLE;
334 msihandle_addref(package->db);
335 return package->db;
338 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
339 MSIHANDLE hRecord)
341 FIXME("STUB: \n");
342 return ERROR_SUCCESS;
345 /* property code */
346 UINT WINAPI MsiSetPropertyA( MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue)
348 LPWSTR szwName = NULL, szwValue = NULL;
349 UINT hr = ERROR_INSTALL_FAILURE;
350 UINT len;
352 if (0 == hInstall) {
353 return ERROR_INVALID_HANDLE;
355 if (NULL == szName) {
356 return ERROR_INVALID_PARAMETER;
358 if (NULL == szValue) {
359 return ERROR_INVALID_PARAMETER;
362 len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
363 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
364 if( !szwName )
365 goto end;
366 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
368 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
369 szwValue = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
370 if( !szwValue)
371 goto end;
372 MultiByteToWideChar( CP_ACP, 0, szValue , -1, szwValue, len );
374 hr = MsiSetPropertyW( hInstall, szwName, szwValue);
376 end:
377 if( szwName )
378 HeapFree( GetProcessHeap(), 0, szwName );
379 if( szwValue )
380 HeapFree( GetProcessHeap(), 0, szwValue );
382 return hr;
385 UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue)
387 MSIPACKAGE *package;
388 MSIHANDLE view,row;
389 UINT rc;
390 DWORD sz = 0;
391 static const CHAR Insert[]=
392 "INSERT into `_Property` (`_Property`,`Value`) VALUES (?)";
394 TRACE("Setting property (%s %s)\n",debugstr_w(szName),
395 debugstr_w(szValue));
397 if (!hInstall)
398 return ERROR_INVALID_HANDLE;
400 rc = MsiGetPropertyW(hInstall,szName,0,&sz);
401 if (rc==ERROR_MORE_DATA || rc == ERROR_SUCCESS)
403 FIXME("Cannot set exising properties! FIXME MIKE!\n");
404 return ERROR_SUCCESS;
407 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
408 if( !package)
409 return ERROR_INVALID_HANDLE;
411 rc = MsiDatabaseOpenViewA(package->db,Insert,&view);
412 if (rc!= ERROR_SUCCESS)
413 return rc;
415 row = MsiCreateRecord(2);
416 MsiRecordSetStringW(row,1,szName);
417 MsiRecordSetStringW(row,2,szValue);
419 rc = MsiViewExecute(view,row);
421 MsiCloseHandle(row);
422 MsiViewClose(view);
423 MsiCloseHandle(view);
425 return rc;
428 UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPSTR szValueBuf, DWORD* pchValueBuf)
430 LPWSTR szwName = NULL, szwValueBuf = NULL;
431 UINT hr = ERROR_INSTALL_FAILURE;
433 if (0 == hInstall) {
434 return ERROR_INVALID_HANDLE;
436 if (NULL == szName) {
437 return ERROR_INVALID_PARAMETER;
440 TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
442 if (NULL != szValueBuf && NULL == pchValueBuf) {
443 return ERROR_INVALID_PARAMETER;
445 if( szName )
447 UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
448 szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
449 if( !szwName )
450 goto end;
451 MultiByteToWideChar( CP_ACP, 0, szName, -1, szwName, len );
452 } else {
453 return ERROR_INVALID_PARAMETER;
455 if( szValueBuf )
457 szwValueBuf = HeapAlloc( GetProcessHeap(), 0, (*pchValueBuf) * sizeof(WCHAR) );
458 if( !szwValueBuf )
459 goto end;
462 hr = MsiGetPropertyW( hInstall, szwName, szwValueBuf, pchValueBuf );
464 if( *pchValueBuf > 0 )
466 WideCharToMultiByte(CP_ACP, 0, szwValueBuf, -1, szValueBuf, *pchValueBuf, NULL, NULL);
469 end:
470 if( szwName )
471 HeapFree( GetProcessHeap(), 0, szwName );
472 if( szwValueBuf )
473 HeapFree( GetProcessHeap(), 0, szwValueBuf );
475 return hr;
478 UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName,
479 LPWSTR szValueBuf, DWORD* pchValueBuf)
481 MSIHANDLE view,row;
482 UINT rc;
483 WCHAR Query[1024]=
484 {'s','e','l','e','c','t',' ','V','a','l','u','e',' ','f','r','o','m',' '
485 ,'_','P','r','o','p','e','r','t','y',' ','w','h','e','r','e',' '
486 ,'_','P','r','o','p','e','r','t','y','=','`',0};
488 static const WCHAR szEnd[]={'`',0};
489 MSIPACKAGE *package;
491 if (0 == hInstall) {
492 return ERROR_INVALID_HANDLE;
494 if (NULL == szName) {
495 return ERROR_INVALID_PARAMETER;
498 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE);
499 if( !package)
500 return ERROR_INVALID_HANDLE;
502 strcatW(Query,szName);
503 strcatW(Query,szEnd);
505 rc = MsiDatabaseOpenViewW(package->db, Query, &view);
506 if (rc == ERROR_SUCCESS)
508 DWORD sz;
509 WCHAR value[0x100];
511 rc = MsiViewExecute(view, 0);
512 if (rc != ERROR_SUCCESS)
514 MsiViewClose(view);
515 MsiCloseHandle(view);
516 return rc;
519 rc = MsiViewFetch(view,&row);
520 if (rc == ERROR_SUCCESS)
522 sz=0x100;
523 rc = MsiRecordGetStringW(row,1,value,&sz);
524 strncpyW(szValueBuf,value,min(sz+1,*pchValueBuf));
525 *pchValueBuf = sz+1;
526 MsiCloseHandle(row);
528 MsiViewClose(view);
529 MsiCloseHandle(view);
532 if (rc == ERROR_SUCCESS)
533 TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
534 debugstr_w(szName));
535 else
537 *pchValueBuf = 0;
538 TRACE("property not found\n");
541 return rc;