2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 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
24 #define NONAMELESSUNION
31 #include "wine/debug.h"
38 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
44 * These apis are defined in MSI 3.0
47 static const WCHAR INSTALLPROPERTY_MEDIAPACKAGEPATH
[] = {'M','e','d','i','a','P','a','c','k','a','g','e','P','a','t','h',0};
48 static const WCHAR INSTALLPROPERTY_DISKPROMPT
[] = {'D','i','s','k','P','r','o','m','p','t',0};
49 static const WCHAR INSTALLPROPERTY_LASTUSEDSOURCE
[] = {'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
50 static const WCHAR INSTALLPROPERTY_LASTUSEDTYPE
[] = {'L','a','s','t','U','s','e','d','T','y','p','e',0};
51 static const WCHAR INSTALLPROPERTY_PACKAGENAME
[] = {'P','a','c','k','a','g','e','N','a','m','e',0};
54 typedef struct tagMediaInfo
61 static UINT
OpenSourceKey(LPCWSTR szProduct
, HKEY
* key
, BOOL user
, BOOL create
)
65 static const WCHAR szSourceList
[] = {'S','o','u','r','c','e','L','i','s','t',0};
68 rc
= MSIREG_OpenUserProductsKey(szProduct
, &rootkey
, create
);
70 rc
= MSIREG_OpenProductsKey(szProduct
, &rootkey
, create
);
76 rc
= RegCreateKeyW(rootkey
, szSourceList
, key
);
78 rc
= RegOpenKeyW(rootkey
,szSourceList
, key
);
83 static UINT
OpenMediaSubkey(HKEY rootkey
, HKEY
*key
, BOOL create
)
86 static const WCHAR media
[] = {'M','e','d','i','a',0};
89 rc
= RegCreateKeyW(rootkey
, media
, key
);
91 rc
= RegOpenKeyW(rootkey
,media
, key
);
96 static UINT
OpenNetworkSubkey(HKEY rootkey
, HKEY
*key
, BOOL create
)
99 static const WCHAR net
[] = {'N','e','t',0};
102 rc
= RegCreateKeyW(rootkey
, net
, key
);
104 rc
= RegOpenKeyW(rootkey
, net
, key
);
109 static UINT
OpenURLSubkey(HKEY rootkey
, HKEY
*key
, BOOL create
)
112 static const WCHAR URL
[] = {'U','R','L',0};
115 rc
= RegCreateKeyW(rootkey
, URL
, key
);
117 rc
= RegOpenKeyW(rootkey
, URL
, key
);
123 static UINT
find_given_source(HKEY key
, LPCWSTR szSource
, media_info
*ss
)
130 UINT rc
= ERROR_SUCCESS
;
132 while (rc
== ERROR_SUCCESS
)
136 rc
= RegEnumValueW(key
, index
, szIndex
, &size
, NULL
, NULL
, NULL
, &val_size
);
137 if (rc
!= ERROR_NO_MORE_ITEMS
)
139 val
= HeapAlloc(GetProcessHeap(),0,val_size
);
140 RegEnumValueW(key
, index
, szIndex
, &size
, NULL
, NULL
, (LPBYTE
)val
,
142 if (lstrcmpiW(szSource
,val
)==0)
145 strcpyW(ss
->szIndex
,szIndex
);
149 strcpyW(ss
->szIndex
,szIndex
);
151 HeapFree(GetProcessHeap(),0,val
);
158 /******************************************************************
159 * MsiSourceListGetInfoW (MSI.@)
161 UINT WINAPI
MsiSourceListGetInfoW( LPCWSTR szProduct
, LPCWSTR szUserSid
,
162 MSIINSTALLCONTEXT dwContext
, DWORD dwOptions
,
163 LPCWSTR szProperty
, LPWSTR szValue
,
169 TRACE("%s %s\n", debugstr_w(szProduct
), debugstr_w(szProperty
));
171 if (!szProduct
|| lstrlenW(szProduct
) > 39)
172 return ERROR_INVALID_PARAMETER
;
174 if (szValue
&& !pcchValue
)
175 return ERROR_INVALID_PARAMETER
;
177 if (dwOptions
== MSICODE_PATCH
)
179 FIXME("Unhandled options MSICODE_PATCH\n");
180 return ERROR_FUNCTION_FAILED
;
184 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid
));
186 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
187 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
189 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
190 rc
= OpenSourceKey(szProduct
, &sourcekey
, FALSE
, FALSE
);
192 rc
= OpenSourceKey(szProduct
, &sourcekey
, TRUE
, FALSE
);
194 if (rc
!= ERROR_SUCCESS
)
195 return ERROR_UNKNOWN_PRODUCT
;
197 if (strcmpW(szProperty
, INSTALLPROPERTY_MEDIAPACKAGEPATH
) == 0)
200 rc
= OpenMediaSubkey(sourcekey
, &key
, FALSE
);
201 if (rc
== ERROR_SUCCESS
)
202 rc
= RegQueryValueExW(key
, INSTALLPROPERTY_MEDIAPACKAGEPATH
, 0, 0,
203 (LPBYTE
)szValue
, pcchValue
);
204 if (rc
!= ERROR_SUCCESS
&& rc
!= ERROR_MORE_DATA
)
205 rc
= ERROR_UNKNOWN_PROPERTY
;
208 else if (strcmpW(szProperty
, INSTALLPROPERTY_DISKPROMPT
) ==0)
211 rc
= OpenMediaSubkey(sourcekey
, &key
, FALSE
);
212 if (rc
== ERROR_SUCCESS
)
213 rc
= RegQueryValueExW(key
, INSTALLPROPERTY_DISKPROMPT
, 0, 0,
214 (LPBYTE
)szValue
, pcchValue
);
215 if (rc
!= ERROR_SUCCESS
&& rc
!= ERROR_MORE_DATA
)
216 rc
= ERROR_UNKNOWN_PROPERTY
;
219 else if (strcmpW(szProperty
, INSTALLPROPERTY_LASTUSEDSOURCE
)==0)
224 RegQueryValueExW(sourcekey
, INSTALLPROPERTY_LASTUSEDSOURCE
, 0, 0, NULL
,
227 rc
= ERROR_UNKNOWN_PROPERTY
;
231 buffer
= HeapAlloc(GetProcessHeap(),0,size
);
232 rc
= RegQueryValueExW(sourcekey
, INSTALLPROPERTY_LASTUSEDSOURCE
, 0,
233 0, (LPBYTE
)buffer
,&size
);
234 ptr
= strchrW(buffer
,';');
235 ptr
= strchrW(ptr
,';');
237 rc
= ERROR_UNKNOWN_PROPERTY
;
241 lstrcpynW(szValue
, ptr
, *pcchValue
);
242 if (lstrlenW(ptr
) > *pcchValue
)
244 *pcchValue
= lstrlenW(ptr
)+1;
245 rc
= ERROR_MORE_DATA
;
250 HeapFree(GetProcessHeap(),0,buffer
);
253 else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPE
, szProperty
)==0)
258 RegQueryValueExW(sourcekey
, INSTALLPROPERTY_LASTUSEDSOURCE
, 0, 0, NULL
,
261 rc
= ERROR_UNKNOWN_PROPERTY
;
264 buffer
= HeapAlloc(GetProcessHeap(),0,size
);
265 rc
= RegQueryValueExW(sourcekey
, INSTALLPROPERTY_LASTUSEDSOURCE
, 0,
266 0, (LPBYTE
)buffer
,&size
);
269 rc
= ERROR_MORE_DATA
;
274 szValue
[0] = buffer
[0];
277 HeapFree(GetProcessHeap(),0,buffer
);
280 else if (strcmpW(INSTALLPROPERTY_PACKAGENAME
, szProperty
)==0)
282 rc
= RegQueryValueExW(sourcekey
, INSTALLPROPERTY_PACKAGENAME
, 0, 0,
283 (LPBYTE
)szValue
, pcchValue
);
284 if (rc
!= ERROR_SUCCESS
&& rc
!= ERROR_MORE_DATA
)
285 rc
= ERROR_UNKNOWN_PROPERTY
;
289 FIXME("Unknown property %s\n",debugstr_w(szProperty
));
290 rc
= ERROR_UNKNOWN_PROPERTY
;
293 RegCloseKey(sourcekey
);
297 /******************************************************************
298 * MsiSourceListSetInfoW (MSI.@)
300 UINT WINAPI
MsiSourceListSetInfoW( LPCWSTR szProduct
, LPCWSTR szUserSid
,
301 MSIINSTALLCONTEXT dwContext
, DWORD dwOptions
,
302 LPCWSTR szProperty
, LPCWSTR szValue
)
307 TRACE("%s %s %x %lx %s %s\n", debugstr_w(szProduct
), debugstr_w(szUserSid
),
308 dwContext
, dwOptions
, debugstr_w(szProperty
), debugstr_w(szValue
));
310 if (!szProduct
|| lstrlenW(szProduct
) > 39)
311 return ERROR_INVALID_PARAMETER
;
313 if (dwOptions
& MSICODE_PATCH
)
315 FIXME("Unhandled options MSICODE_PATCH\n");
316 return ERROR_FUNCTION_FAILED
;
320 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid
));
322 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
323 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
325 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
326 rc
= OpenSourceKey(szProduct
, &sourcekey
, FALSE
, TRUE
);
328 rc
= OpenSourceKey(szProduct
, &sourcekey
, TRUE
, TRUE
);
330 if (rc
!= ERROR_SUCCESS
)
331 return ERROR_UNKNOWN_PRODUCT
;
334 if (strcmpW(szProperty
, INSTALLPROPERTY_MEDIAPACKAGEPATH
) == 0)
337 DWORD size
= lstrlenW(szValue
)*sizeof(WCHAR
);
338 rc
= OpenMediaSubkey(sourcekey
, &key
, FALSE
);
339 if (rc
== ERROR_SUCCESS
)
340 rc
= RegSetValueExW(key
, INSTALLPROPERTY_MEDIAPACKAGEPATH
, 0,
341 REG_SZ
, (LPBYTE
)szValue
, size
);
342 if (rc
!= ERROR_SUCCESS
)
343 rc
= ERROR_UNKNOWN_PROPERTY
;
346 else if (strcmpW(szProperty
, INSTALLPROPERTY_DISKPROMPT
) ==0)
349 DWORD size
= lstrlenW(szValue
)*sizeof(WCHAR
);
350 rc
= OpenMediaSubkey(sourcekey
, &key
, FALSE
);
351 if (rc
== ERROR_SUCCESS
)
352 rc
= RegSetValueExW(key
, INSTALLPROPERTY_DISKPROMPT
, 0, REG_SZ
,
353 (LPBYTE
)szValue
, size
);
354 if (rc
!= ERROR_SUCCESS
)
355 rc
= ERROR_UNKNOWN_PROPERTY
;
358 else if (strcmpW(szProperty
, INSTALLPROPERTY_LASTUSEDSOURCE
)==0)
360 LPWSTR buffer
= NULL
;
362 WCHAR typechar
= 'n';
363 static const WCHAR LastUsedSource_Fmt
[] = {'%','c',';','%','i',';','%','s',0};
365 /* make sure the source is registered */
366 MsiSourceListAddSourceExW(szProduct
, szUserSid
, dwContext
,
367 dwOptions
, szValue
, 0);
369 if (dwOptions
& MSISOURCETYPE_NETWORK
)
371 else if (dwOptions
& MSISOURCETYPE_URL
)
373 else if (dwOptions
& MSISOURCETYPE_MEDIA
)
376 ERR("Unknown source type! 0x%lx\n",dwOptions
);
378 size
= (lstrlenW(szValue
)+5)*sizeof(WCHAR
);
379 buffer
= HeapAlloc(GetProcessHeap(),0,size
);
380 sprintfW(buffer
, LastUsedSource_Fmt
, typechar
, 1, szValue
);
381 rc
= RegSetValueExW(sourcekey
, INSTALLPROPERTY_LASTUSEDSOURCE
, 0,
382 REG_EXPAND_SZ
, (LPBYTE
)buffer
, size
);
383 if (rc
!= ERROR_SUCCESS
)
384 rc
= ERROR_UNKNOWN_PROPERTY
;
385 HeapFree( GetProcessHeap(), 0, buffer
);
387 else if (strcmpW(INSTALLPROPERTY_PACKAGENAME
, szProperty
)==0)
389 DWORD size
= lstrlenW(szValue
)*sizeof(WCHAR
);
390 rc
= RegSetValueExW(sourcekey
, INSTALLPROPERTY_PACKAGENAME
, 0, REG_SZ
,
391 (LPBYTE
)szValue
, size
);
392 if (rc
!= ERROR_SUCCESS
)
393 rc
= ERROR_UNKNOWN_PROPERTY
;
397 FIXME("Unknown property %s\n",debugstr_w(szProperty
));
398 rc
= ERROR_UNKNOWN_PROPERTY
;
401 RegCloseKey(sourcekey
);
406 /******************************************************************
407 * MsiSourceListAddSourceExW (MSI.@)
409 UINT WINAPI
MsiSourceListAddSourceExW( LPCWSTR szProduct
, LPCWSTR szUserSid
,
410 MSIINSTALLCONTEXT dwContext
, DWORD dwOptions
, LPCWSTR szSource
,
416 media_info source_struct
;
418 TRACE("%s, %s, %x, %lx, %s, %li\n", debugstr_w(szProduct
),
419 debugstr_w(szUserSid
), dwContext
, dwOptions
, debugstr_w(szSource
),
423 return ERROR_INVALID_PARAMETER
;
426 return ERROR_INVALID_PARAMETER
;
428 if (dwOptions
& MSICODE_PATCH
)
430 FIXME("Unhandled options MSICODE_PATCH\n");
431 return ERROR_FUNCTION_FAILED
;
435 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid
));
437 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
438 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
440 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
441 rc
= OpenSourceKey(szProduct
, &sourcekey
, FALSE
, TRUE
);
443 rc
= OpenSourceKey(szProduct
, &sourcekey
, TRUE
, TRUE
);
445 if (rc
!= ERROR_SUCCESS
)
446 return ERROR_UNKNOWN_PRODUCT
;
448 if (dwOptions
& MSISOURCETYPE_NETWORK
)
449 rc
= OpenNetworkSubkey(sourcekey
, &typekey
, TRUE
);
450 else if (dwOptions
& MSISOURCETYPE_URL
)
451 rc
= OpenURLSubkey(sourcekey
, &typekey
, TRUE
);
454 ERR("Unknown media type!\n");
455 RegCloseKey(sourcekey
);
456 return ERROR_FUNCTION_FAILED
;
459 source_struct
.szIndex
[0] = 0;
460 if (find_given_source(typekey
, szSource
, &source_struct
)==ERROR_SUCCESS
)
462 DWORD current_index
= atoiW(source_struct
.szIndex
);
463 /* found the source */
464 if (dwIndex
> 0 && current_index
!= dwIndex
)
465 FIXME("Need to reorder the souces! UNHANDLED\n");
469 DWORD current_index
= 0;
470 static const WCHAR fmt
[] = {'%','i',0};
471 DWORD size
= lstrlenW(szSource
)*sizeof(WCHAR
);
473 if (source_struct
.szIndex
[0])
474 current_index
= atoiW(source_struct
.szIndex
);
476 if (dwIndex
> 0 && dwIndex
< current_index
)
477 FIXME("Need to reorder the souces! UNHANDLED\n");
480 sprintfW(source_struct
.szIndex
,fmt
,current_index
);
481 rc
= RegSetValueExW(typekey
, source_struct
.szIndex
, 0, REG_EXPAND_SZ
,
482 (LPBYTE
)szSource
, size
);
485 RegCloseKey(typekey
);
486 RegCloseKey(sourcekey
);
490 /******************************************************************
491 * MsiSourceListAddMediaDisk(MSI.@)
493 UINT WINAPI
MsiSourceListAddMediaDiskW(LPCWSTR szProduct
, LPCWSTR szUserSid
,
494 MSIINSTALLCONTEXT dwContext
, DWORD dwOptions
, DWORD dwDiskId
,
495 LPCWSTR szVolumeLabel
, LPCWSTR szDiskPrompt
)
501 static const WCHAR fmt
[] = {'%','i',0};
502 static const WCHAR disk_fmt
[] = {'%','s',';','%','s',0};
503 static const WCHAR empty
[1] = {0};
508 TRACE("%s %s %x %lx %li %s %s\n", debugstr_w(szProduct
),
509 debugstr_w(szUserSid
), dwContext
, dwOptions
, dwDiskId
,
510 debugstr_w(szVolumeLabel
), debugstr_w(szDiskPrompt
));
512 if (!szProduct
|| lstrlenW(szProduct
) > 39)
513 return ERROR_INVALID_PARAMETER
;
515 if (dwOptions
& MSICODE_PATCH
)
517 FIXME("Unhandled options MSICODE_PATCH\n");
518 return ERROR_FUNCTION_FAILED
;
522 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid
));
524 if (dwContext
== MSIINSTALLCONTEXT_USERUNMANAGED
)
525 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
527 if (dwContext
== MSIINSTALLCONTEXT_MACHINE
)
528 rc
= OpenSourceKey(szProduct
, &sourcekey
, FALSE
, TRUE
);
530 rc
= OpenSourceKey(szProduct
, &sourcekey
, TRUE
, TRUE
);
532 if (rc
!= ERROR_SUCCESS
)
533 return ERROR_UNKNOWN_PRODUCT
;
535 OpenMediaSubkey(sourcekey
,&mediakey
,TRUE
);
537 sprintfW(szIndex
,fmt
,dwDiskId
);
542 size
+=lstrlenW(szVolumeLabel
);
549 size
+=lstrlenW(szDiskPrompt
);
555 size
*=sizeof(WCHAR
);
557 buffer
= HeapAlloc(GetProcessHeap(),0,size
);
558 sprintfW(buffer
,disk_fmt
,pt1
,pt2
);
560 RegSetValueExW(mediakey
, szIndex
, 0, REG_SZ
, (LPBYTE
)buffer
, size
);
561 HeapFree( GetProcessHeap(), 0, buffer
);
563 RegCloseKey(sourcekey
);
564 RegCloseKey(mediakey
);
566 return ERROR_SUCCESS
;