save old text color during a call of DrawCaptionTempW
[wine/kumbayo.git] / dlls / msi / source.c
blob68f94b549ccf3d71b1d8c252d7689ab5a621a85d
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winnls.h"
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "msi.h"
33 #include "msiquery.h"
34 #include "msipriv.h"
35 #include "wincrypt.h"
36 #include "winver.h"
37 #include "winuser.h"
38 #include "wine/unicode.h"
39 #include "sddl.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 * These apis are defined in MSI 3.0
47 typedef struct tagMediaInfo
49 struct list entry;
50 LPWSTR path;
51 WCHAR szIndex[10];
52 DWORD index;
53 } media_info;
55 static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, DWORD dwOptions,
56 MSIINSTALLCONTEXT context, BOOL create)
58 HKEY rootkey = 0;
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);
66 else
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);
73 else
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);
80 else
81 rc = MSIREG_OpenLocalClassesProductKey(szProduct, &rootkey, create);
84 if (rc)
86 if (dwOptions == MSICODE_PATCH)
87 return ERROR_UNKNOWN_PATCH;
88 else
89 return ERROR_UNKNOWN_PRODUCT;
92 if (create)
93 rc = RegCreateKeyW(rootkey, szSourceList, key);
94 else
96 rc = RegOpenKeyW(rootkey,szSourceList, key);
97 if (rc != ERROR_SUCCESS)
98 rc = ERROR_BAD_CONFIGURATION;
101 return rc;
104 static UINT OpenMediaSubkey(HKEY rootkey, HKEY *key, BOOL create)
106 UINT rc;
107 static const WCHAR media[] = {'M','e','d','i','a',0};
109 if (create)
110 rc = RegCreateKeyW(rootkey, media, key);
111 else
112 rc = RegOpenKeyW(rootkey,media, key);
114 return rc;
117 static UINT OpenNetworkSubkey(HKEY rootkey, HKEY *key, BOOL create)
119 UINT rc;
120 static const WCHAR net[] = {'N','e','t',0};
122 if (create)
123 rc = RegCreateKeyW(rootkey, net, key);
124 else
125 rc = RegOpenKeyW(rootkey, net, key);
127 return rc;
130 static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
132 UINT rc;
133 static const WCHAR URL[] = {'U','R','L',0};
135 if (create)
136 rc = RegCreateKeyW(rootkey, URL, key);
137 else
138 rc = RegOpenKeyW(rootkey, URL, key);
140 return rc;
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,
162 LPDWORD pcchValue)
164 UINT ret;
165 LPWSTR product = NULL;
166 LPWSTR usersid = NULL;
167 LPWSTR property = NULL;
168 LPWSTR value = NULL;
169 DWORD len = 0;
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)
181 goto done;
183 value = msi_alloc(++len * sizeof(WCHAR));
184 if (!value)
185 return ERROR_OUTOFMEMORY;
187 *value = '\0';
188 ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
189 property, value, &len);
190 if (ret != ERROR_SUCCESS)
191 goto done;
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);
196 else if (szValue)
197 ret = ERROR_MORE_DATA;
199 *pcchValue = len - 1;
201 done:
202 msi_free(product);
203 msi_free(usersid);
204 msi_free(property);
205 msi_free(value);
206 return ret;
209 /******************************************************************
210 * MsiSourceListGetInfoW (MSI.@)
212 UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
213 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
214 LPCWSTR szProperty, LPWSTR szValue,
215 LPDWORD pcchValue)
217 HKEY sourcekey;
218 UINT rc;
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;
237 if (!szProperty)
238 return ERROR_INVALID_PARAMETER;
240 if (szUserSid)
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)
248 return rc;
250 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
252 HKEY key;
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;
259 RegCloseKey(key);
261 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) ==0)
263 HKEY key;
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;
270 RegCloseKey(key);
272 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
274 LPWSTR buffer;
275 DWORD size = 0;
277 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
278 NULL, &size);
279 if (size == 0)
280 rc = ERROR_UNKNOWN_PROPERTY;
281 else
283 LPWSTR ptr;
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,';');
289 if (!ptr)
290 rc = ERROR_UNKNOWN_PROPERTY;
291 else
293 ptr ++;
294 lstrcpynW(szValue, ptr, *pcchValue);
295 if (lstrlenW(ptr) > *pcchValue)
297 *pcchValue = lstrlenW(ptr)+1;
298 rc = ERROR_MORE_DATA;
300 else
301 rc = ERROR_SUCCESS;
303 msi_free(buffer);
306 else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPEW, szProperty)==0)
308 LPWSTR buffer;
309 DWORD size = 0;
311 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
312 NULL, &size);
313 if (size == 0)
314 rc = ERROR_UNKNOWN_PROPERTY;
315 else
317 buffer = msi_alloc(size);
318 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
319 0, 0, (LPBYTE)buffer,&size);
320 if (*pcchValue < 1)
322 rc = ERROR_MORE_DATA;
323 *pcchValue = 1;
325 else
327 szValue[0] = buffer[0];
328 rc = ERROR_SUCCESS;
330 msi_free(buffer);
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)
340 *pcchValue = 0;
341 rc = ERROR_SUCCESS;
343 else
345 if (*pcchValue)
346 *pcchValue = (*pcchValue - 1) / sizeof(WCHAR);
347 if (szValue)
348 szValue[*pcchValue] = '\0';
351 else
353 FIXME("Unknown property %s\n",debugstr_w(szProperty));
354 rc = ERROR_UNKNOWN_PROPERTY;
357 RegCloseKey(sourcekey);
358 return rc;
361 /******************************************************************
362 * MsiSourceListSetInfoW (MSI.@)
364 UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
365 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
366 LPCWSTR szProperty, LPCWSTR szValue)
368 HKEY sourcekey;
369 UINT rc;
371 TRACE("%s %s %x %x %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid),
372 dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
374 if (!szProduct || lstrlenW(szProduct) > 39)
375 return ERROR_INVALID_PARAMETER;
377 if (dwOptions & MSICODE_PATCH)
379 FIXME("Unhandled options MSICODE_PATCH\n");
380 return ERROR_FUNCTION_FAILED;
383 if (szUserSid)
384 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
386 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
387 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
389 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, TRUE);
390 if (rc != ERROR_SUCCESS)
391 return ERROR_UNKNOWN_PRODUCT;
394 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
396 HKEY key;
397 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
398 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
399 if (rc == ERROR_SUCCESS)
400 rc = RegSetValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW, 0,
401 REG_SZ, (const BYTE *)szValue, size);
402 if (rc != ERROR_SUCCESS)
403 rc = ERROR_UNKNOWN_PROPERTY;
404 RegCloseKey(key);
406 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) == 0)
408 HKEY key;
409 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
410 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
411 if (rc == ERROR_SUCCESS)
412 rc = RegSetValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0,
413 REG_SZ, (const BYTE *)szValue, size);
414 if (rc != ERROR_SUCCESS)
415 rc = ERROR_UNKNOWN_PROPERTY;
416 RegCloseKey(key);
418 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
420 LPWSTR buffer = NULL;
421 DWORD size;
422 WCHAR typechar = 'n';
423 static const WCHAR LastUsedSource_Fmt[] = {'%','c',';','%','i',';','%','s',0};
425 /* make sure the source is registered */
426 MsiSourceListAddSourceExW(szProduct, szUserSid, dwContext,
427 dwOptions, szValue, 0);
429 if (dwOptions & MSISOURCETYPE_NETWORK)
430 typechar = 'n';
431 else if (dwOptions & MSISOURCETYPE_URL)
432 typechar = 'u';
433 else if (dwOptions & MSISOURCETYPE_MEDIA)
434 typechar = 'm';
435 else
436 ERR("Unknown source type! %x\n", dwOptions);
438 size = (lstrlenW(szValue)+5)*sizeof(WCHAR);
439 buffer = msi_alloc(size);
440 sprintfW(buffer, LastUsedSource_Fmt, typechar, 1, szValue);
441 rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0,
442 REG_EXPAND_SZ, (LPBYTE)buffer, size);
443 if (rc != ERROR_SUCCESS)
444 rc = ERROR_UNKNOWN_PROPERTY;
445 msi_free( buffer );
447 else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
449 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
450 rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
451 REG_SZ, (const BYTE *)szValue, size);
452 if (rc != ERROR_SUCCESS)
453 rc = ERROR_UNKNOWN_PROPERTY;
455 else
457 FIXME("Unknown property %s\n",debugstr_w(szProperty));
458 rc = ERROR_UNKNOWN_PROPERTY;
461 RegCloseKey(sourcekey);
462 return rc;
466 /******************************************************************
467 * MsiSourceListAddSourceW (MSI.@)
469 UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
470 DWORD dwReserved, LPCWSTR szSource)
472 INT ret;
473 LPWSTR sidstr = NULL;
474 DWORD sidsize = 0;
475 DWORD domsize = 0;
477 TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource));
479 if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL))
481 PSID psid = msi_alloc(sidsize);
483 if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL))
484 ConvertSidToStringSidW(psid, &sidstr);
486 msi_free(psid);
489 ret = MsiSourceListAddSourceExW(szProduct, sidstr,
490 MSIINSTALLCONTEXT_USERMANAGED, MSISOURCETYPE_NETWORK, szSource, 0);
492 if (sidstr)
493 LocalFree(sidstr);
495 return ret;
498 /******************************************************************
499 * MsiSourceListAddSourceA (MSI.@)
501 UINT WINAPI MsiSourceListAddSourceA( LPCSTR szProduct, LPCSTR szUserName,
502 DWORD dwReserved, LPCSTR szSource)
504 INT ret;
505 LPWSTR szwproduct;
506 LPWSTR szwusername;
507 LPWSTR szwsource;
509 szwproduct = strdupAtoW( szProduct );
510 szwusername = strdupAtoW( szUserName );
511 szwsource = strdupAtoW( szSource );
513 ret = MsiSourceListAddSourceW(szwproduct, szwusername, 0, szwsource);
515 msi_free(szwproduct);
516 msi_free(szwusername);
517 msi_free(szwsource);
519 return ret;
522 /******************************************************************
523 * MsiSourceListAddSourceExA (MSI.@)
525 UINT WINAPI MsiSourceListAddSourceExA(LPCSTR szProduct, LPCSTR szUserSid,
526 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource, DWORD dwIndex)
528 UINT ret;
529 LPWSTR product, usersid, source;
531 product = strdupAtoW(szProduct);
532 usersid = strdupAtoW(szUserSid);
533 source = strdupAtoW(szSource);
535 ret = MsiSourceListAddSourceExW(product, usersid, dwContext,
536 dwOptions, source, dwIndex);
538 msi_free(product);
539 msi_free(usersid);
540 msi_free(source);
542 return ret;
545 static void free_source_list(struct list *sourcelist)
547 while (!list_empty(sourcelist))
549 media_info *info = LIST_ENTRY(list_head(sourcelist), media_info, entry);
550 list_remove(&info->entry);
551 msi_free(info->path);
552 msi_free(info);
556 static void add_source_to_list(struct list *sourcelist, media_info *info)
558 media_info *iter;
559 BOOL found = FALSE;
560 static const WCHAR fmt[] = {'%','i',0};
562 if (list_empty(sourcelist))
564 list_add_head(sourcelist, &info->entry);
565 return;
568 LIST_FOR_EACH_ENTRY(iter, sourcelist, media_info, entry)
570 if (!found && info->index < iter->index)
572 found = TRUE;
573 list_add_before(&iter->entry, &info->entry);
576 /* update the rest of the list */
577 if (found)
578 sprintfW(iter->szIndex, fmt, ++iter->index);
581 if (!found)
582 list_add_after(&iter->entry, &info->entry);
585 static UINT fill_source_list(struct list *sourcelist, HKEY sourcekey, DWORD *count)
587 UINT r = ERROR_SUCCESS;
588 DWORD index = 0;
589 WCHAR name[10];
590 DWORD size, val_size;
591 media_info *entry;
593 *count = 0;
595 while (r == ERROR_SUCCESS)
597 size = sizeof(name) / sizeof(name[0]);
598 r = RegEnumValueW(sourcekey, index, name, &size, NULL, NULL, NULL, &val_size);
599 if (r != ERROR_SUCCESS)
600 return r;
602 entry = msi_alloc(sizeof(media_info));
603 if (!entry)
604 goto error;
606 entry->path = msi_alloc(val_size);
607 if (!entry->path)
608 goto error;
610 lstrcpyW(entry->szIndex, name);
611 entry->index = atoiW(name);
613 size++;
614 r = RegEnumValueW(sourcekey, index, name, &size, NULL,
615 NULL, (LPBYTE)entry->path, &val_size);
616 if (r != ERROR_SUCCESS)
617 goto error;
619 index = ++(*count);
620 add_source_to_list(sourcelist, entry);
623 error:
624 *count = -1;
625 free_source_list(sourcelist);
626 return ERROR_OUTOFMEMORY;
629 /******************************************************************
630 * MsiSourceListAddSourceExW (MSI.@)
632 UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
633 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource,
634 DWORD dwIndex)
636 HKEY sourcekey;
637 HKEY typekey;
638 UINT rc;
639 struct list sourcelist;
640 media_info *info;
641 WCHAR squished_pc[GUID_SIZE];
642 WCHAR name[10];
643 LPWSTR source;
644 LPCWSTR postfix;
645 DWORD size, count;
647 static const WCHAR fmt[] = {'%','i',0};
648 static const WCHAR one[] = {'1',0};
649 static const WCHAR backslash[] = {'\\',0};
650 static const WCHAR forwardslash[] = {'/',0};
652 TRACE("%s %s %x %x %s %i\n", debugstr_w(szProduct), debugstr_w(szUserSid),
653 dwContext, dwOptions, debugstr_w(szSource), dwIndex);
655 if (!szProduct || !squash_guid(szProduct, squished_pc))
656 return ERROR_INVALID_PARAMETER;
658 if (!szSource || !*szSource)
659 return ERROR_INVALID_PARAMETER;
661 if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
662 return ERROR_INVALID_PARAMETER;
664 if (dwOptions & MSICODE_PATCH)
666 FIXME("Unhandled options MSICODE_PATCH\n");
667 return ERROR_FUNCTION_FAILED;
670 if (szUserSid && (dwContext & MSIINSTALLCONTEXT_MACHINE))
671 return ERROR_INVALID_PARAMETER;
673 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
674 if (rc != ERROR_SUCCESS)
675 return rc;
677 if (dwOptions & MSISOURCETYPE_NETWORK)
678 rc = OpenNetworkSubkey(sourcekey, &typekey, TRUE);
679 else if (dwOptions & MSISOURCETYPE_URL)
680 rc = OpenURLSubkey(sourcekey, &typekey, TRUE);
681 else if (dwOptions & MSISOURCETYPE_MEDIA)
682 rc = OpenMediaSubkey(sourcekey, &typekey, TRUE);
683 else
685 ERR("unknown media type: %08x\n", dwOptions);
686 RegCloseKey(sourcekey);
687 return ERROR_FUNCTION_FAILED;
690 postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? backslash : forwardslash;
691 if (szSource[lstrlenW(szSource) - 1] == *postfix)
692 source = strdupW(szSource);
693 else
695 size = lstrlenW(szSource) + 2;
696 source = msi_alloc(size * sizeof(WCHAR));
697 lstrcpyW(source, szSource);
698 lstrcatW(source, postfix);
701 list_init(&sourcelist);
702 rc = fill_source_list(&sourcelist, typekey, &count);
703 if (rc != ERROR_NO_MORE_ITEMS)
704 return rc;
706 size = (lstrlenW(source) + 1) * sizeof(WCHAR);
708 if (count == 0)
710 rc = RegSetValueExW(typekey, one, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
711 goto done;
713 else if (dwIndex > count)
715 sprintfW(name, fmt, count + 1);
716 rc = RegSetValueExW(typekey, name, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
717 goto done;
719 else
721 /* add to the end of the list */
722 if (dwIndex == 0)
723 dwIndex = count + 1;
725 sprintfW(name, fmt, dwIndex);
726 info = msi_alloc(sizeof(media_info));
727 if (!info)
729 rc = ERROR_OUTOFMEMORY;
730 goto done;
733 info->path = strdupW(source);
734 lstrcpyW(info->szIndex, name);
735 info->index = dwIndex;
736 add_source_to_list(&sourcelist, info);
738 LIST_FOR_EACH_ENTRY(info, &sourcelist, media_info, entry)
740 size = (lstrlenW(info->path) + 1) * sizeof(WCHAR);
741 rc = RegSetValueExW(typekey, info->szIndex, 0,
742 REG_EXPAND_SZ, (LPBYTE)info->path, size);
743 if (rc != ERROR_SUCCESS)
744 goto done;
748 done:
749 free_source_list(&sourcelist);
750 msi_free(source);
751 RegCloseKey(typekey);
752 RegCloseKey(sourcekey);
753 return rc;
756 /******************************************************************
757 * MsiSourceListAddMediaDisk(MSI.@)
759 UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
760 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId,
761 LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
763 HKEY sourcekey;
764 HKEY mediakey;
765 UINT rc;
766 WCHAR szIndex[10];
767 static const WCHAR fmt[] = {'%','i',0};
768 static const WCHAR disk_fmt[] = {'%','s',';','%','s',0};
769 static const WCHAR empty[1] = {0};
770 LPCWSTR pt1,pt2;
771 LPWSTR buffer;
772 DWORD size;
774 TRACE("%s %s %x %x %i %s %s\n", debugstr_w(szProduct),
775 debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId,
776 debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt));
778 if (!szProduct || lstrlenW(szProduct) > 39)
779 return ERROR_INVALID_PARAMETER;
781 if (dwOptions & MSICODE_PATCH)
783 FIXME("Unhandled options MSICODE_PATCH\n");
784 return ERROR_FUNCTION_FAILED;
787 if (szUserSid)
788 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
790 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
791 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
793 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, TRUE);
794 if (rc != ERROR_SUCCESS)
795 return ERROR_UNKNOWN_PRODUCT;
797 OpenMediaSubkey(sourcekey,&mediakey,TRUE);
799 sprintfW(szIndex,fmt,dwDiskId);
801 size = 2;
802 if (szVolumeLabel)
804 size +=lstrlenW(szVolumeLabel);
805 pt1 = szVolumeLabel;
807 else
808 pt1 = empty;
809 if (szDiskPrompt)
811 size +=lstrlenW(szDiskPrompt);
812 pt2 = szDiskPrompt;
814 else
815 pt2 = empty;
817 size *=sizeof(WCHAR);
819 buffer = msi_alloc(size);
820 sprintfW(buffer,disk_fmt,pt1,pt2);
822 RegSetValueExW(mediakey, szIndex, 0, REG_SZ, (LPBYTE)buffer, size);
823 msi_free( buffer );
825 RegCloseKey(sourcekey);
826 RegCloseKey(mediakey);
828 return ERROR_SUCCESS;
831 /******************************************************************
832 * MsiSourceListClearAllA (MSI.@)
834 UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved )
836 FIXME("(%s %s %d)\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved);
837 return ERROR_SUCCESS;
840 /******************************************************************
841 * MsiSourceListClearAllW (MSI.@)
843 UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved )
845 FIXME("(%s %s %d)\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved);
846 return ERROR_SUCCESS;