wgl: Remove the pixel format limitation.
[wine/testsucceed.git] / dlls / msi / source.c
blobc373df256036a296ff38b297710cda8198127052
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 != ERROR_SUCCESS)
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 LPWSTR product = NULL;
152 LPWSTR usersid = NULL;
153 LPWSTR source = NULL;
154 DWORD len = 0;
155 UINT r = ERROR_INVALID_PARAMETER;
156 static int index = 0;
158 TRACE("(%s, %s, %d, %d, %d, %p, %p)\n", debugstr_a(szProductCodeOrPatch),
159 debugstr_a(szUserSid), dwContext, dwOptions, dwIndex, szSource, pcchSource);
161 if (dwIndex == 0)
162 index = 0;
164 if (szSource && !pcchSource)
165 goto done;
167 if (dwIndex != index)
168 goto done;
170 if (szProductCodeOrPatch) product = strdupAtoW(szProductCodeOrPatch);
171 if (szUserSid) usersid = strdupAtoW(szUserSid);
173 r = MsiSourceListEnumSourcesW(product, usersid, dwContext, dwOptions,
174 dwIndex, NULL, &len);
175 if (r != ERROR_SUCCESS)
176 goto done;
178 source = msi_alloc(++len * sizeof(WCHAR));
179 if (!source)
181 r = ERROR_OUTOFMEMORY;
182 goto done;
185 *source = '\0';
186 r = MsiSourceListEnumSourcesW(product, usersid, dwContext, dwOptions,
187 dwIndex, source, &len);
188 if (r != ERROR_SUCCESS)
189 goto done;
191 len = WideCharToMultiByte(CP_ACP, 0, source, -1, NULL, 0, NULL, NULL);
192 if (pcchSource && *pcchSource >= len)
193 WideCharToMultiByte(CP_ACP, 0, source, -1, szSource, len, NULL, NULL);
194 else if (szSource)
195 r = ERROR_MORE_DATA;
197 if (pcchSource)
198 *pcchSource = len - 1;
200 done:
201 msi_free(product);
202 msi_free(usersid);
203 msi_free(source);
205 if (r == ERROR_SUCCESS)
207 if (szSource || !pcchSource) index++;
209 else if (dwIndex > index)
210 index = 0;
212 return r;
215 /******************************************************************
216 * MsiSourceListEnumSourcesW (MSI.@)
218 UINT WINAPI MsiSourceListEnumSourcesW(LPCWSTR szProductCodeOrPatch, LPCWSTR szUserSid,
219 MSIINSTALLCONTEXT dwContext,
220 DWORD dwOptions, DWORD dwIndex,
221 LPWSTR szSource, LPDWORD pcchSource)
223 WCHAR squished_pc[GUID_SIZE];
224 WCHAR name[32];
225 HKEY source = NULL;
226 HKEY subkey = NULL;
227 LONG res;
228 UINT r = ERROR_INVALID_PARAMETER;
229 static int index = 0;
231 static const WCHAR format[] = {'%','d',0};
233 TRACE("(%s, %s, %d, %d, %d, %p, %p)\n", debugstr_w(szProductCodeOrPatch),
234 debugstr_w(szUserSid), dwContext, dwOptions, dwIndex, szSource, pcchSource);
236 if (dwIndex == 0)
237 index = 0;
239 if (!szProductCodeOrPatch || !squash_guid(szProductCodeOrPatch, squished_pc))
240 goto done;
242 if (szSource && !pcchSource)
243 goto done;
245 if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
246 goto done;
248 if ((dwOptions & MSISOURCETYPE_NETWORK) && (dwOptions & MSISOURCETYPE_URL))
249 goto done;
251 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
252 goto done;
254 if (dwIndex != index)
255 goto done;
257 r = OpenSourceKey(szProductCodeOrPatch, &source,
258 dwOptions, dwContext, FALSE);
259 if (r != ERROR_SUCCESS)
260 goto done;
262 if (dwOptions & MSISOURCETYPE_NETWORK)
263 r = OpenNetworkSubkey(source, &subkey, FALSE);
264 else if (dwOptions & MSISOURCETYPE_URL)
265 r = OpenURLSubkey(source, &subkey, FALSE);
267 if (r != ERROR_SUCCESS)
269 r = ERROR_NO_MORE_ITEMS;
270 goto done;
273 sprintfW(name, format, dwIndex + 1);
275 res = RegQueryValueExW(subkey, name, 0, 0, (LPBYTE)szSource, pcchSource);
276 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
277 r = ERROR_NO_MORE_ITEMS;
279 done:
280 RegCloseKey(subkey);
281 RegCloseKey(source);
283 if (r == ERROR_SUCCESS)
285 if (szSource || !pcchSource) index++;
287 else if (dwIndex > index)
288 index = 0;
290 return r;
293 /******************************************************************
294 * MsiSourceListGetInfoA (MSI.@)
296 UINT WINAPI MsiSourceListGetInfoA( LPCSTR szProduct, LPCSTR szUserSid,
297 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
298 LPCSTR szProperty, LPSTR szValue,
299 LPDWORD pcchValue)
301 UINT ret;
302 LPWSTR product = NULL;
303 LPWSTR usersid = NULL;
304 LPWSTR property = NULL;
305 LPWSTR value = NULL;
306 DWORD len = 0;
308 if (szValue && !pcchValue)
309 return ERROR_INVALID_PARAMETER;
311 if (szProduct) product = strdupAtoW(szProduct);
312 if (szUserSid) usersid = strdupAtoW(szUserSid);
313 if (szProperty) property = strdupAtoW(szProperty);
315 ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
316 property, NULL, &len);
317 if (ret != ERROR_SUCCESS)
318 goto done;
320 value = msi_alloc(++len * sizeof(WCHAR));
321 if (!value)
322 return ERROR_OUTOFMEMORY;
324 *value = '\0';
325 ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
326 property, value, &len);
327 if (ret != ERROR_SUCCESS)
328 goto done;
330 len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
331 if (*pcchValue >= len)
332 WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
333 else if (szValue)
334 ret = ERROR_MORE_DATA;
336 *pcchValue = len - 1;
338 done:
339 msi_free(product);
340 msi_free(usersid);
341 msi_free(property);
342 msi_free(value);
343 return ret;
346 /******************************************************************
347 * MsiSourceListGetInfoW (MSI.@)
349 UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
350 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
351 LPCWSTR szProperty, LPWSTR szValue,
352 LPDWORD pcchValue)
354 HKEY sourcekey;
355 UINT rc;
357 TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szProperty));
359 if (!szProduct || !*szProduct)
360 return ERROR_INVALID_PARAMETER;
362 if (lstrlenW(szProduct) != GUID_SIZE - 1 ||
363 (szProduct[0] != '{' && szProduct[GUID_SIZE - 2] != '}'))
364 return ERROR_INVALID_PARAMETER;
366 if (szValue && !pcchValue)
367 return ERROR_INVALID_PARAMETER;
369 if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
370 dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
371 dwContext != MSIINSTALLCONTEXT_MACHINE)
372 return ERROR_INVALID_PARAMETER;
374 if (!szProperty)
375 return ERROR_INVALID_PARAMETER;
377 if (szUserSid)
378 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
380 if (dwContext != MSIINSTALLCONTEXT_USERUNMANAGED)
381 FIXME("Unhandled context %d\n", dwContext);
383 rc = OpenSourceKey(szProduct, &sourcekey, dwOptions, dwContext, FALSE);
384 if (rc != ERROR_SUCCESS)
385 return rc;
387 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) == 0)
389 HKEY key;
390 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
391 if (rc == ERROR_SUCCESS)
392 rc = RegQueryValueExW(key, INSTALLPROPERTY_MEDIAPACKAGEPATHW,
393 0, 0, (LPBYTE)szValue, pcchValue);
394 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
395 rc = ERROR_UNKNOWN_PROPERTY;
396 RegCloseKey(key);
398 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW) ==0)
400 HKEY key;
401 rc = OpenMediaSubkey(sourcekey, &key, FALSE);
402 if (rc == ERROR_SUCCESS)
403 rc = RegQueryValueExW(key, INSTALLPROPERTY_DISKPROMPTW, 0, 0,
404 (LPBYTE)szValue, pcchValue);
405 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
406 rc = ERROR_UNKNOWN_PROPERTY;
407 RegCloseKey(key);
409 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
411 LPWSTR buffer;
412 DWORD size = 0;
414 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
415 NULL, &size);
416 if (size == 0)
417 rc = ERROR_UNKNOWN_PROPERTY;
418 else
420 LPWSTR ptr;
421 buffer = msi_alloc(size);
422 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
423 0, 0, (LPBYTE)buffer,&size);
424 ptr = strchrW(buffer,';');
425 if (ptr) ptr = strchrW(ptr+1,';');
426 if (!ptr)
427 rc = ERROR_UNKNOWN_PROPERTY;
428 else
430 ptr ++;
431 lstrcpynW(szValue, ptr, *pcchValue);
432 if (lstrlenW(ptr) > *pcchValue)
434 *pcchValue = lstrlenW(ptr)+1;
435 rc = ERROR_MORE_DATA;
437 else
438 rc = ERROR_SUCCESS;
440 msi_free(buffer);
443 else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPEW, szProperty)==0)
445 LPWSTR buffer;
446 DWORD size = 0;
448 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW, 0, 0,
449 NULL, &size);
450 if (size == 0)
451 rc = ERROR_UNKNOWN_PROPERTY;
452 else
454 buffer = msi_alloc(size);
455 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
456 0, 0, (LPBYTE)buffer,&size);
457 if (*pcchValue < 1)
459 rc = ERROR_MORE_DATA;
460 *pcchValue = 1;
462 else
464 szValue[0] = buffer[0];
465 rc = ERROR_SUCCESS;
467 msi_free(buffer);
470 else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
472 *pcchValue = *pcchValue * sizeof(WCHAR);
473 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
474 (LPBYTE)szValue, pcchValue);
475 if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
477 *pcchValue = 0;
478 rc = ERROR_SUCCESS;
480 else
482 if (*pcchValue)
483 *pcchValue = (*pcchValue - 1) / sizeof(WCHAR);
484 if (szValue)
485 szValue[*pcchValue] = '\0';
488 else
490 FIXME("Unknown property %s\n",debugstr_w(szProperty));
491 rc = ERROR_UNKNOWN_PROPERTY;
494 RegCloseKey(sourcekey);
495 return rc;
498 /******************************************************************
499 * MsiSourceListSetInfoA (MSI.@)
501 UINT WINAPI MsiSourceListSetInfoA(LPCSTR szProduct, LPCSTR szUserSid,
502 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
503 LPCSTR szProperty, LPCSTR szValue)
505 UINT ret;
506 LPWSTR product = NULL;
507 LPWSTR usersid = NULL;
508 LPWSTR property = NULL;
509 LPWSTR value = NULL;
511 if (szProduct) product = strdupAtoW(szProduct);
512 if (szUserSid) usersid = strdupAtoW(szUserSid);
513 if (szProperty) property = strdupAtoW(szProperty);
514 if (szValue) value = strdupAtoW(szValue);
516 ret = MsiSourceListSetInfoW(product, usersid, dwContext, dwOptions,
517 property, value);
519 msi_free(product);
520 msi_free(usersid);
521 msi_free(property);
522 msi_free(value);
524 return ret;
527 static UINT set_last_used_source(HKEY source, LPCWSTR product, LPCWSTR usersid,
528 MSIINSTALLCONTEXT context, DWORD options,
529 LPCWSTR value)
531 LPWSTR buffer;
532 WCHAR typechar;
533 DWORD size;
534 UINT r;
535 int index = 0;
537 static const WCHAR format[] = {'%','c',';','%','i',';','%','s',0};
539 if (options & MSISOURCETYPE_NETWORK)
540 typechar = 'n';
541 else if (options & MSISOURCETYPE_URL)
542 typechar = 'u';
543 else
544 return ERROR_INVALID_PARAMETER;
546 /* make sure the source is registered */
547 r = MsiSourceListAddSourceExW(product, usersid, context,
548 options, value, 0);
549 if (r != ERROR_SUCCESS)
550 return r;
552 while ((r = MsiSourceListEnumSourcesW(product, usersid, context, options,
553 index, NULL, NULL)) == ERROR_SUCCESS)
554 index++;
556 if (r != ERROR_NO_MORE_ITEMS)
557 return r;
559 size = (lstrlenW(format) + lstrlenW(value) + 7) * sizeof(WCHAR);
560 buffer = msi_alloc(size);
561 if (!buffer)
562 return ERROR_OUTOFMEMORY;
564 sprintfW(buffer, format, typechar, index, value);
566 size = (lstrlenW(buffer) + 1) * sizeof(WCHAR);
567 r = RegSetValueExW(source, INSTALLPROPERTY_LASTUSEDSOURCEW, 0,
568 REG_SZ, (LPBYTE)buffer, size);
569 msi_free(buffer);
571 return r;
574 /******************************************************************
575 * MsiSourceListSetInfoW (MSI.@)
577 UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
578 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
579 LPCWSTR szProperty, LPCWSTR szValue)
581 WCHAR squished_pc[GUID_SIZE];
582 HKEY sourcekey, media;
583 LPCWSTR property;
584 UINT rc;
586 static const WCHAR media_package[] = {
587 'M','e','d','i','a','P','a','c','k','a','g','e',0
590 TRACE("%s %s %x %x %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid),
591 dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
593 if (!szProduct || !squash_guid(szProduct, squished_pc))
594 return ERROR_INVALID_PARAMETER;
596 if (!szProperty)
597 return ERROR_INVALID_PARAMETER;
599 if (!szValue)
600 return ERROR_UNKNOWN_PROPERTY;
602 if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
603 return ERROR_INVALID_PARAMETER;
605 if (dwOptions & MSICODE_PATCH)
607 FIXME("Unhandled options MSICODE_PATCH\n");
608 return ERROR_UNKNOWN_PATCH;
611 property = szProperty;
612 if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW))
613 property = media_package;
615 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
616 if (rc != ERROR_SUCCESS)
617 return rc;
619 if (lstrcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW) &&
620 dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
622 RegCloseKey(sourcekey);
623 return ERROR_INVALID_PARAMETER;
626 if (!lstrcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW) ||
627 !lstrcmpW(szProperty, INSTALLPROPERTY_DISKPROMPTW))
629 rc = OpenMediaSubkey(sourcekey, &media, TRUE);
630 if (rc == ERROR_SUCCESS)
632 rc = msi_reg_set_val_str(media, property, szValue);
633 RegCloseKey(media);
636 else if (strcmpW(INSTALLPROPERTY_PACKAGENAMEW, szProperty)==0)
638 DWORD size = lstrlenW(szValue)*sizeof(WCHAR);
639 rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
640 REG_SZ, (const BYTE *)szValue, size);
641 if (rc != ERROR_SUCCESS)
642 rc = ERROR_UNKNOWN_PROPERTY;
644 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW)==0)
645 rc = set_last_used_source(sourcekey, szProduct, szUserSid, dwContext,
646 dwOptions, szValue);
647 else
648 rc = ERROR_UNKNOWN_PROPERTY;
650 RegCloseKey(sourcekey);
651 return rc;
655 /******************************************************************
656 * MsiSourceListAddSourceW (MSI.@)
658 UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
659 DWORD dwReserved, LPCWSTR szSource)
661 INT ret;
662 LPWSTR sidstr = NULL;
663 DWORD sidsize = 0;
664 DWORD domsize = 0;
666 TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource));
668 if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL))
670 PSID psid = msi_alloc(sidsize);
672 if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL))
673 ConvertSidToStringSidW(psid, &sidstr);
675 msi_free(psid);
678 ret = MsiSourceListAddSourceExW(szProduct, sidstr,
679 MSIINSTALLCONTEXT_USERMANAGED, MSISOURCETYPE_NETWORK, szSource, 0);
681 if (sidstr)
682 LocalFree(sidstr);
684 return ret;
687 /******************************************************************
688 * MsiSourceListAddSourceA (MSI.@)
690 UINT WINAPI MsiSourceListAddSourceA( LPCSTR szProduct, LPCSTR szUserName,
691 DWORD dwReserved, LPCSTR szSource)
693 INT ret;
694 LPWSTR szwproduct;
695 LPWSTR szwusername;
696 LPWSTR szwsource;
698 szwproduct = strdupAtoW( szProduct );
699 szwusername = strdupAtoW( szUserName );
700 szwsource = strdupAtoW( szSource );
702 ret = MsiSourceListAddSourceW(szwproduct, szwusername, 0, szwsource);
704 msi_free(szwproduct);
705 msi_free(szwusername);
706 msi_free(szwsource);
708 return ret;
711 /******************************************************************
712 * MsiSourceListAddSourceExA (MSI.@)
714 UINT WINAPI MsiSourceListAddSourceExA(LPCSTR szProduct, LPCSTR szUserSid,
715 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource, DWORD dwIndex)
717 UINT ret;
718 LPWSTR product, usersid, source;
720 product = strdupAtoW(szProduct);
721 usersid = strdupAtoW(szUserSid);
722 source = strdupAtoW(szSource);
724 ret = MsiSourceListAddSourceExW(product, usersid, dwContext,
725 dwOptions, source, dwIndex);
727 msi_free(product);
728 msi_free(usersid);
729 msi_free(source);
731 return ret;
734 static void free_source_list(struct list *sourcelist)
736 while (!list_empty(sourcelist))
738 media_info *info = LIST_ENTRY(list_head(sourcelist), media_info, entry);
739 list_remove(&info->entry);
740 msi_free(info->path);
741 msi_free(info);
745 static void add_source_to_list(struct list *sourcelist, media_info *info)
747 media_info *iter;
748 BOOL found = FALSE;
749 static const WCHAR fmt[] = {'%','i',0};
751 if (list_empty(sourcelist))
753 list_add_head(sourcelist, &info->entry);
754 return;
757 LIST_FOR_EACH_ENTRY(iter, sourcelist, media_info, entry)
759 if (!found && info->index < iter->index)
761 found = TRUE;
762 list_add_before(&iter->entry, &info->entry);
765 /* update the rest of the list */
766 if (found)
767 sprintfW(iter->szIndex, fmt, ++iter->index);
770 if (!found)
771 list_add_after(&iter->entry, &info->entry);
774 static UINT fill_source_list(struct list *sourcelist, HKEY sourcekey, DWORD *count)
776 UINT r = ERROR_SUCCESS;
777 DWORD index = 0;
778 WCHAR name[10];
779 DWORD size, val_size;
780 media_info *entry;
782 *count = 0;
784 while (r == ERROR_SUCCESS)
786 size = sizeof(name) / sizeof(name[0]);
787 r = RegEnumValueW(sourcekey, index, name, &size, NULL, NULL, NULL, &val_size);
788 if (r != ERROR_SUCCESS)
789 return r;
791 entry = msi_alloc(sizeof(media_info));
792 if (!entry)
793 goto error;
795 entry->path = msi_alloc(val_size);
796 if (!entry->path)
798 msi_free(entry);
799 goto error;
802 lstrcpyW(entry->szIndex, name);
803 entry->index = atoiW(name);
805 size++;
806 r = RegEnumValueW(sourcekey, index, name, &size, NULL,
807 NULL, (LPBYTE)entry->path, &val_size);
808 if (r != ERROR_SUCCESS)
810 msi_free(entry->path);
811 msi_free(entry);
812 goto error;
815 index = ++(*count);
816 add_source_to_list(sourcelist, entry);
819 error:
820 *count = -1;
821 free_source_list(sourcelist);
822 return ERROR_OUTOFMEMORY;
825 /******************************************************************
826 * MsiSourceListAddSourceExW (MSI.@)
828 UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
829 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource,
830 DWORD dwIndex)
832 HKEY sourcekey;
833 HKEY typekey;
834 UINT rc;
835 struct list sourcelist;
836 media_info *info;
837 WCHAR squished_pc[GUID_SIZE];
838 WCHAR name[10];
839 LPWSTR source;
840 LPCWSTR postfix;
841 DWORD size, count;
843 static const WCHAR fmt[] = {'%','i',0};
844 static const WCHAR one[] = {'1',0};
845 static const WCHAR backslash[] = {'\\',0};
846 static const WCHAR forwardslash[] = {'/',0};
848 TRACE("%s %s %x %x %s %i\n", debugstr_w(szProduct), debugstr_w(szUserSid),
849 dwContext, dwOptions, debugstr_w(szSource), dwIndex);
851 if (!szProduct || !squash_guid(szProduct, squished_pc))
852 return ERROR_INVALID_PARAMETER;
854 if (!szSource || !*szSource)
855 return ERROR_INVALID_PARAMETER;
857 if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
858 return ERROR_INVALID_PARAMETER;
860 if (dwOptions & MSICODE_PATCH)
862 FIXME("Unhandled options MSICODE_PATCH\n");
863 return ERROR_FUNCTION_FAILED;
866 if (szUserSid && (dwContext & MSIINSTALLCONTEXT_MACHINE))
867 return ERROR_INVALID_PARAMETER;
869 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
870 if (rc != ERROR_SUCCESS)
871 return rc;
873 if (dwOptions & MSISOURCETYPE_NETWORK)
874 rc = OpenNetworkSubkey(sourcekey, &typekey, TRUE);
875 else if (dwOptions & MSISOURCETYPE_URL)
876 rc = OpenURLSubkey(sourcekey, &typekey, TRUE);
877 else if (dwOptions & MSISOURCETYPE_MEDIA)
878 rc = OpenMediaSubkey(sourcekey, &typekey, TRUE);
879 else
881 ERR("unknown media type: %08x\n", dwOptions);
882 RegCloseKey(sourcekey);
883 return ERROR_FUNCTION_FAILED;
886 postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? backslash : forwardslash;
887 if (szSource[lstrlenW(szSource) - 1] == *postfix)
888 source = strdupW(szSource);
889 else
891 size = lstrlenW(szSource) + 2;
892 source = msi_alloc(size * sizeof(WCHAR));
893 lstrcpyW(source, szSource);
894 lstrcatW(source, postfix);
897 list_init(&sourcelist);
898 rc = fill_source_list(&sourcelist, typekey, &count);
899 if (rc != ERROR_NO_MORE_ITEMS)
900 return rc;
902 size = (lstrlenW(source) + 1) * sizeof(WCHAR);
904 if (count == 0)
906 rc = RegSetValueExW(typekey, one, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
907 goto done;
909 else if (dwIndex > count)
911 sprintfW(name, fmt, count + 1);
912 rc = RegSetValueExW(typekey, name, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
913 goto done;
915 else
917 /* add to the end of the list */
918 if (dwIndex == 0)
919 dwIndex = count + 1;
921 sprintfW(name, fmt, dwIndex);
922 info = msi_alloc(sizeof(media_info));
923 if (!info)
925 rc = ERROR_OUTOFMEMORY;
926 goto done;
929 info->path = strdupW(source);
930 lstrcpyW(info->szIndex, name);
931 info->index = dwIndex;
932 add_source_to_list(&sourcelist, info);
934 LIST_FOR_EACH_ENTRY(info, &sourcelist, media_info, entry)
936 size = (lstrlenW(info->path) + 1) * sizeof(WCHAR);
937 rc = RegSetValueExW(typekey, info->szIndex, 0,
938 REG_EXPAND_SZ, (LPBYTE)info->path, size);
939 if (rc != ERROR_SUCCESS)
940 goto done;
944 done:
945 free_source_list(&sourcelist);
946 msi_free(source);
947 RegCloseKey(typekey);
948 RegCloseKey(sourcekey);
949 return rc;
952 /******************************************************************
953 * MsiSourceListAddMediaDisk(MSI.@)
955 UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
956 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId,
957 LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
959 HKEY sourcekey;
960 HKEY mediakey;
961 UINT rc;
962 WCHAR szIndex[10];
963 static const WCHAR fmt[] = {'%','i',0};
964 static const WCHAR disk_fmt[] = {'%','s',';','%','s',0};
965 static const WCHAR empty[1] = {0};
966 LPCWSTR pt1,pt2;
967 LPWSTR buffer;
968 DWORD size;
970 TRACE("%s %s %x %x %i %s %s\n", debugstr_w(szProduct),
971 debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId,
972 debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt));
974 if (!szProduct || lstrlenW(szProduct) > 39)
975 return ERROR_INVALID_PARAMETER;
977 if (dwOptions & MSICODE_PATCH)
979 FIXME("Unhandled options MSICODE_PATCH\n");
980 return ERROR_FUNCTION_FAILED;
983 if (szUserSid)
984 FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
986 if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED)
987 FIXME("Unknown context MSIINSTALLCONTEXT_USERUNMANAGED\n");
989 rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, TRUE);
990 if (rc != ERROR_SUCCESS)
991 return ERROR_UNKNOWN_PRODUCT;
993 OpenMediaSubkey(sourcekey,&mediakey,TRUE);
995 sprintfW(szIndex,fmt,dwDiskId);
997 size = 2;
998 if (szVolumeLabel)
1000 size +=lstrlenW(szVolumeLabel);
1001 pt1 = szVolumeLabel;
1003 else
1004 pt1 = empty;
1005 if (szDiskPrompt)
1007 size +=lstrlenW(szDiskPrompt);
1008 pt2 = szDiskPrompt;
1010 else
1011 pt2 = empty;
1013 size *=sizeof(WCHAR);
1015 buffer = msi_alloc(size);
1016 sprintfW(buffer,disk_fmt,pt1,pt2);
1018 RegSetValueExW(mediakey, szIndex, 0, REG_SZ, (LPBYTE)buffer, size);
1019 msi_free( buffer );
1021 RegCloseKey(sourcekey);
1022 RegCloseKey(mediakey);
1024 return ERROR_SUCCESS;
1027 /******************************************************************
1028 * MsiSourceListClearAllA (MSI.@)
1030 UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved )
1032 FIXME("(%s %s %d)\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved);
1033 return ERROR_SUCCESS;
1036 /******************************************************************
1037 * MsiSourceListClearAllW (MSI.@)
1039 UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved )
1041 FIXME("(%s %s %d)\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved);
1042 return ERROR_SUCCESS;