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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 typedef struct tagMediaInfo
55 static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, DWORD dwOptions,
56 MSIINSTALLCONTEXT context, BOOL create)
59 UINT rc = ERROR_FUNCTION_FAILED;
60 static const WCHAR szSourceList[] = {'S','o','u','r','c','e','L','i','s','t',0};
62 if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
64 if (dwOptions == MSICODE_PATCH)
65 rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
67 rc = MSIREG_OpenUserProductsKey(szProduct, &rootkey, create);
69 else if (context == MSIINSTALLCONTEXT_USERMANAGED)
71 if (dwOptions == MSICODE_PATCH)
72 rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
74 rc = MSIREG_OpenLocalManagedProductKey(szProduct, &rootkey, create);
76 else if (context == MSIINSTALLCONTEXT_MACHINE)
78 if (dwOptions == MSICODE_PATCH)
79 rc = MSIREG_OpenPatchesKey(szProduct, &rootkey, create);
81 rc = MSIREG_OpenLocalClassesProductKey(szProduct, &rootkey, create);
86 if (dwOptions == MSICODE_PATCH)
87 return ERROR_UNKNOWN_PATCH;
89 return ERROR_UNKNOWN_PRODUCT;
93 rc = RegCreateKeyW(rootkey, szSourceList, key);
96 rc = RegOpenKeyW(rootkey,szSourceList, key);
97 if (rc != ERROR_SUCCESS)
98 rc = ERROR_BAD_CONFIGURATION;
104 static UINT OpenMediaSubkey(HKEY rootkey, HKEY *key, BOOL create)
107 static const WCHAR media[] = {'M','e','d','i','a',0};
110 rc = RegCreateKeyW(rootkey, media, key);
112 rc = RegOpenKeyW(rootkey,media, key);
117 static UINT OpenNetworkSubkey(HKEY rootkey, HKEY *key, BOOL create)
120 static const WCHAR net[] = {'N','e','t',0};
123 rc = RegCreateKeyW(rootkey, net, key);
125 rc = RegOpenKeyW(rootkey, net, key);
130 static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
133 static const WCHAR URL[] = {'U','R','L',0};
136 rc = RegCreateKeyW(rootkey, URL, key);
138 rc = RegOpenKeyW(rootkey, URL, key);
143 /******************************************************************
144 * MsiSourceListEnumSourcesA (MSI.@)
146 UINT WINAPI MsiSourceListEnumSourcesA(LPCSTR szProductCodeOrPatch, LPCSTR szUserSid,
147 MSIINSTALLCONTEXT dwContext,
148 DWORD dwOptions, DWORD dwIndex,
149 LPSTR szSource, LPDWORD pcchSource)
151 FIXME("(%s, %s, %d, %d, %d, %p, %p): stub!\n", szProductCodeOrPatch, szUserSid,
152 dwContext, dwOptions, dwIndex, szSource, pcchSource);
153 return ERROR_CALL_NOT_IMPLEMENTED;
156 /******************************************************************
157 * MsiSourceListGetInfoA (MSI.@)
159 UINT WINAPI MsiSourceListGetInfoA( LPCSTR szProduct, LPCSTR szUserSid,
160 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
161 LPCSTR szProperty, LPSTR szValue,
165 LPWSTR product = NULL;
166 LPWSTR usersid = NULL;
167 LPWSTR property = NULL;
171 if (szValue && !pcchValue)
172 return ERROR_INVALID_PARAMETER;
174 if (szProduct) product = strdupAtoW(szProduct);
175 if (szUserSid) usersid = strdupAtoW(szUserSid);
176 if (szProperty) property = strdupAtoW(szProperty);
178 ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
179 property, NULL, &len);
180 if (ret != ERROR_SUCCESS)
183 value = msi_alloc(++len * sizeof(WCHAR));
185 return ERROR_OUTOFMEMORY;
188 ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
189 property, value, &len);
190 if (ret != ERROR_SUCCESS)
193 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
194 if (*pcchValue >= len)
195 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
197 ret = ERROR_MORE_DATA;
199 *pcchValue = len - 1;
209 /******************************************************************
210 * MsiSourceListGetInfoW (MSI.@)
212 UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
213 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
214 LPCWSTR szProperty, LPWSTR szValue,
220 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szProperty));
222 if (!szProduct || !*szProduct)
223 return ERROR_INVALID_PARAMETER;
225 if (lstrlenW(szProduct) != GUID_SIZE - 1 ||
226 (szProduct[0] != '{' && szProduct[GUID_SIZE - 2] != '}'))
227 return ERROR_INVALID_PARAMETER;
229 if (szValue && !pcchValue)
230 return ERROR_INVALID_PARAMETER;
232 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
233 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
234 dwContext != MSIINSTALLCONTEXT_MACHINE)
235 return ERROR_INVALID_PARAMETER;
238 return ERROR_INVALID_PARAMETER;
241 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
243 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED)
244 FIXME("Unhandled context %d\n", dwContext);
246 rc = OpenSourceKey(szProduct, &sourcekey, dwOptions, dwContext, FALSE);
247 if (rc != ERROR_SUCCESS)
250 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
253 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
254 if (rc == ERROR_SUCCESS)
255 rc = RegQueryValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW,
256 0, 0, (LPBYTE)szValue, pcchValue);
257 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
258 rc = ERROR_UNKNOWN_PROPERTY;
261 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) ==0)
264 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
265 if (rc == ERROR_SUCCESS)
266 rc = RegQueryValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0, 0,
267 (LPBYTE)szValue, pcchValue);
268 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
269 rc = ERROR_UNKNOWN_PROPERTY;
272 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
277 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
280 rc = ERROR_UNKNOWN_PROPERTY;
284 buffer = msi_alloc(size);
285 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
286 0, 0, (LPBYTE)buffer,&size);
287 ptr = strchrW(buffer,';');
288 if (ptr) ptr = strchrW(ptr+1,';');
290 rc = ERROR_UNKNOWN_PROPERTY;
294 lstrcpynW(szValue, ptr, *pcchValue);
295 if (lstrlenW(ptr) > *pcchValue)
297 *pcchValue = lstrlenW(ptr)+1;
298 rc = ERROR_MORE_DATA;
306 else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPEW, szProperty)==0)
311 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
314 rc = ERROR_UNKNOWN_PROPERTY;
317 buffer = msi_alloc(size);
318 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
319 0, 0, (LPBYTE)buffer,&size);
322 rc = ERROR_MORE_DATA;
327 szValue[0] = buffer[0];
333 else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
335 *pcchValue = *pcchValue * sizeof(WCHAR);
336 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
337 (LPBYTE)szValue, pcchValue);
338 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
346 *pcchValue = (*pcchValue - 1) / sizeof(WCHAR);
348 szValue[*pcchValue] = '\0';
353 FIXME("Unknown property %s\n",debugstr_w(szProperty));
354 rc = ERROR_UNKNOWN_PROPERTY;
357 RegCloseKey(sourcekey);
361 /******************************************************************
362 * MsiSourceListSetInfoA (MSI.@)
364 UINT WINAPI MsiSourceListSetInfoA(LPCSTR szProduct, LPCSTR szUserSid,
365 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
366 LPCSTR szProperty, LPCSTR szValue)
369 LPWSTR product = NULL;
370 LPWSTR usersid = NULL;
371 LPWSTR property = NULL;
374 if (szProduct) product = strdupAtoW(szProduct);
375 if (szUserSid) usersid = strdupAtoW(szUserSid);
376 if (szProperty) property = strdupAtoW(szProperty);
377 if (szValue) value = strdupAtoW(szValue);
379 ret = MsiSourceListSetInfoW(product, usersid, dwContext, dwOptions,
390 /******************************************************************
391 * MsiSourceListSetInfoW (MSI.@)
393 UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
394 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
395 LPCWSTR szProperty, LPCWSTR szValue)
400 TRACE("%s %s %x %x %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid),
401 dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
403 if (!szProduct || lstrlenW(szProduct) > 39)
404 return ERROR_INVALID_PARAMETER;
407 return ERROR_INVALID_PARAMETER;
410 return ERROR_UNKNOWN_PROPERTY;
412 if (dwOptions & MSICODE_PATCH)
414 FIXME("Unhandled options MSICODE_PATCH\n");
415 return ERROR_FUNCTION_FAILED;
419 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
421 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
422 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
424 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
425 if (rc != ERROR_SUCCESS)
426 return ERROR_UNKNOWN_PRODUCT;
429 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
432 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
433 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
434 if (rc == ERROR_SUCCESS)
435 rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW, 0,
436 REG_SZ, (const BYTE *)szValue, size);
437 if (rc != ERROR_SUCCESS)
438 rc = ERROR_UNKNOWN_PROPERTY;
441 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) == 0)
444 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
445 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
446 if (rc == ERROR_SUCCESS)
447 rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0,
448 REG_SZ, (const BYTE *)szValue, size);
449 if (rc != ERROR_SUCCESS)
450 rc = ERROR_UNKNOWN_PROPERTY;
453 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
455 LPWSTR buffer = NULL;
457 WCHAR typechar = 'n';
458 static const WCHAR LastUsedSource_Fmt[] = {'%','c',';','%','i',';','%','s',0};
460 /* make sure the source is registered */
461 MsiSourceListAddSourceExW(szProduct, szUserSid, dwContext,
462 dwOptions, szValue, 0);
464 if (dwOptions & MSISOURCETYPE_NETWORK)
466 else if (dwOptions & MSISOURCETYPE_URL)
468 else if (dwOptions & MSISOURCETYPE_MEDIA)
471 ERR("Unknown source type! %x\n", dwOptions);
473 size = (lstrlenW(szValue)+5)*sizeof(WCHAR);
474 buffer = msi_alloc(size);
475 sprintfW(buffer, LastUsedSource_Fmt, typechar, 1, szValue);
476 rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0,
477 REG_EXPAND_SZ, (LPBYTE)buffer, size);
478 if (rc != ERROR_SUCCESS)
479 rc = ERROR_UNKNOWN_PROPERTY;
482 else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
484 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
485 rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
486 REG_SZ, (const BYTE *)szValue, size);
487 if (rc != ERROR_SUCCESS)
488 rc = ERROR_UNKNOWN_PROPERTY;
492 FIXME("Unknown property %s\n",debugstr_w(szProperty));
493 rc = ERROR_UNKNOWN_PROPERTY;
496 RegCloseKey(sourcekey);
501 /******************************************************************
502 * MsiSourceListAddSourceW (MSI.@)
504 UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
505 DWORD dwReserved, LPCWSTR szSource)
508 LPWSTR sidstr = NULL;
512 TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource));
514 if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL))
516 PSID psid = msi_alloc(sidsize);
518 if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL))
519 ConvertSidToStringSidW(psid, &sidstr);
524 ret = MsiSourceListAddSourceExW(szProduct, sidstr,
525 MSIINSTALLCONTEXT_USERMANAGED, MSISOURCETYPE_NETWORK, szSource, 0);
533 /******************************************************************
534 * MsiSourceListAddSourceA (MSI.@)
536 UINT WINAPI MsiSourceListAddSourceA( LPCSTR szProduct, LPCSTR szUserName,
537 DWORD dwReserved, LPCSTR szSource)
544 szwproduct = strdupAtoW( szProduct );
545 szwusername = strdupAtoW( szUserName );
546 szwsource = strdupAtoW( szSource );
548 ret = MsiSourceListAddSourceW(szwproduct, szwusername, 0, szwsource);
550 msi_free(szwproduct);
551 msi_free(szwusername);
557 /******************************************************************
558 * MsiSourceListAddSourceExA (MSI.@)
560 UINT WINAPI MsiSourceListAddSourceExA(LPCSTR szProduct, LPCSTR szUserSid,
561 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource, DWORD dwIndex)
564 LPWSTR product, usersid, source;
566 product = strdupAtoW(szProduct);
567 usersid = strdupAtoW(szUserSid);
568 source = strdupAtoW(szSource);
570 ret = MsiSourceListAddSourceExW(product, usersid, dwContext,
571 dwOptions, source, dwIndex);
580 static void free_source_list(struct list *sourcelist)
582 while (!list_empty(sourcelist))
584 media_info *info = LIST_ENTRY(list_head(sourcelist), media_info, entry);
585 list_remove(&info->entry);
586 msi_free(info->path);
591 static void add_source_to_list(struct list *sourcelist, media_info *info)
595 static const WCHAR fmt[] = {'%','i',0};
597 if (list_empty(sourcelist))
599 list_add_head(sourcelist, &info->entry);
603 LIST_FOR_EACH_ENTRY(iter, sourcelist, media_info, entry)
605 if (!found && info->index < iter->index)
608 list_add_before(&iter->entry, &info->entry);
611 /* update the rest of the list */
613 sprintfW(iter->szIndex, fmt, ++iter->index);
617 list_add_after(&iter->entry, &info->entry);
620 static UINT fill_source_list(struct list *sourcelist, HKEY sourcekey, DWORD *count)
622 UINT r = ERROR_SUCCESS;
625 DWORD size, val_size;
630 while (r == ERROR_SUCCESS)
632 size = sizeof(name) / sizeof(name[0]);
633 r = RegEnumValueW(sourcekey, index, name, &size, NULL, NULL, NULL, &val_size);
634 if (r != ERROR_SUCCESS)
637 entry = msi_alloc(sizeof(media_info));
641 entry->path = msi_alloc(val_size);
648 lstrcpyW(entry->szIndex, name);
649 entry->index = atoiW(name);
652 r = RegEnumValueW(sourcekey, index, name, &size, NULL,
653 NULL, (LPBYTE)entry->path, &val_size);
654 if (r != ERROR_SUCCESS)
656 msi_free(entry->path);
662 add_source_to_list(sourcelist, entry);
667 free_source_list(sourcelist);
668 return ERROR_OUTOFMEMORY;
671 /******************************************************************
672 * MsiSourceListAddSourceExW (MSI.@)
674 UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
675 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource,
681 struct list sourcelist;
683 WCHAR squished_pc[GUID_SIZE];
689 static const WCHAR fmt[] = {'%','i',0};
690 static const WCHAR one[] = {'1',0};
691 static const WCHAR backslash[] = {'\\',0};
692 static const WCHAR forwardslash[] = {'/',0};
694 TRACE("%s %s %x %x %s %i\n", debugstr_w(szProduct), debugstr_w(szUserSid),
695 dwContext, dwOptions, debugstr_w(szSource), dwIndex);
697 if (!szProduct || !squash_guid(szProduct, squished_pc))
698 return ERROR_INVALID_PARAMETER;
700 if (!szSource || !*szSource)
701 return ERROR_INVALID_PARAMETER;
703 if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
704 return ERROR_INVALID_PARAMETER;
706 if (dwOptions & MSICODE_PATCH)
708 FIXME("Unhandled options MSICODE_PATCH\n");
709 return ERROR_FUNCTION_FAILED;
712 if (szUserSid && (dwContext & MSIINSTALLCONTEXT_MACHINE))
713 return ERROR_INVALID_PARAMETER;
715 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
716 if (rc != ERROR_SUCCESS)
719 if (dwOptions & MSISOURCETYPE_NETWORK)
720 rc = OpenNetworkSubkey(sourcekey, &typekey, TRUE);
721 else if (dwOptions & MSISOURCETYPE_URL)
722 rc = OpenURLSubkey(sourcekey, &typekey, TRUE);
723 else if (dwOptions & MSISOURCETYPE_MEDIA)
724 rc = OpenMediaSubkey(sourcekey, &typekey, TRUE);
727 ERR("unknown media type: %08x\n", dwOptions);
728 RegCloseKey(sourcekey);
729 return ERROR_FUNCTION_FAILED;
732 postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? backslash : forwardslash;
733 if (szSource[lstrlenW(szSource) - 1] == *postfix)
734 source = strdupW(szSource);
737 size = lstrlenW(szSource) + 2;
738 source = msi_alloc(size * sizeof(WCHAR));
739 lstrcpyW(source, szSource);
740 lstrcatW(source, postfix);
743 list_init(&sourcelist);
744 rc = fill_source_list(&sourcelist, typekey, &count);
745 if (rc != ERROR_NO_MORE_ITEMS)
748 size = (lstrlenW(source) + 1) * sizeof(WCHAR);
752 rc = RegSetValueExW(typekey, one, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
755 else if (dwIndex > count)
757 sprintfW(name, fmt, count + 1);
758 rc = RegSetValueExW(typekey, name, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
763 /* add to the end of the list */
767 sprintfW(name, fmt, dwIndex);
768 info = msi_alloc(sizeof(media_info));
771 rc = ERROR_OUTOFMEMORY;
775 info->path = strdupW(source);
776 lstrcpyW(info->szIndex, name);
777 info->index = dwIndex;
778 add_source_to_list(&sourcelist, info);
780 LIST_FOR_EACH_ENTRY(info, &sourcelist, media_info, entry)
782 size = (lstrlenW(info->path) + 1) * sizeof(WCHAR);
783 rc = RegSetValueExW(typekey, info->szIndex, 0,
784 REG_EXPAND_SZ, (LPBYTE)info->path, size);
785 if (rc != ERROR_SUCCESS)
791 free_source_list(&sourcelist);
793 RegCloseKey(typekey);
794 RegCloseKey(sourcekey);
798 /******************************************************************
799 * MsiSourceListAddMediaDisk(MSI.@)
801 UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
802 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId,
803 LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
809 static const WCHAR fmt[] = {'%','i',0};
810 static const WCHAR disk_fmt[] = {'%','s',';','%','s',0};
811 static const WCHAR empty[1] = {0};
816 TRACE("%s %s %x %x %i %s %s\n", debugstr_w(szProduct),
817 debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId,
818 debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt));
820 if (!szProduct || lstrlenW(szProduct) > 39)
821 return ERROR_INVALID_PARAMETER;
823 if (dwOptions & MSICODE_PATCH)
825 FIXME("Unhandled options MSICODE_PATCH\n");
826 return ERROR_FUNCTION_FAILED;
830 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
832 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
833 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
835 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, TRUE);
836 if (rc != ERROR_SUCCESS)
837 return ERROR_UNKNOWN_PRODUCT;
839 OpenMediaSubkey(sourcekey,&mediakey,TRUE);
841 sprintfW(szIndex,fmt,dwDiskId);
846 size +=lstrlenW(szVolumeLabel);
853 size +=lstrlenW(szDiskPrompt);
859 size *=sizeof(WCHAR);
861 buffer = msi_alloc(size);
862 sprintfW(buffer,disk_fmt,pt1,pt2);
864 RegSetValueExW(mediakey, szIndex, 0, REG_SZ, (LPBYTE)buffer, size);
867 RegCloseKey(sourcekey);
868 RegCloseKey(mediakey);
870 return ERROR_SUCCESS;
873 /******************************************************************
874 * MsiSourceListClearAllA (MSI.@)
876 UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved )
878 FIXME("(%s %s %d)\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved);
879 return ERROR_SUCCESS;
882 /******************************************************************
883 * MsiSourceListClearAllW (MSI.@)
885 UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved )
887 FIXME("(%s %s %d)\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved);
888 return ERROR_SUCCESS;