Add source.c to start handling the various MsiSourceList apis used in
[wine/multimedia.git] / dlls / msi / source.c
blobb1db1b27a20264bcd9dffc5d7273b3961f1e1785
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "action.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
56 LPWSTR path;
57 WCHAR szIndex[10];
58 WCHAR type;
59 } media_info;
61 static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, BOOL user, BOOL create)
63 HKEY rootkey = 0;
64 UINT rc;
65 static const WCHAR szSourceList[] = {'S','o','u','r','c','e','L','i','s','t',0};
67 if (user)
68 rc = MSIREG_OpenUserProductsKey(szProduct, &rootkey, create);
69 else
70 rc = MSIREG_OpenProductsKey(szProduct, &rootkey, create);
72 if (rc)
73 return rc;
75 if (create)
76 rc = RegCreateKeyW(rootkey, szSourceList, key);
77 else
78 rc = RegOpenKeyW(rootkey,szSourceList, key);
80 return rc;
83 static UINT OpenMediaSubkey(HKEY rootkey, HKEY *key, BOOL create)
85 UINT rc;
86 static const WCHAR media[] = {'M','e','d','i','a',0};
88 if (create)
89 rc = RegCreateKeyW(rootkey, media, key);
90 else
91 rc = RegOpenKeyW(rootkey,media, key);
93 return rc;
96 static UINT OpenNetworkSubkey(HKEY rootkey, HKEY *key, BOOL create)
98 UINT rc;
99 static const WCHAR net[] = {'N','e','t',0};
101 if (create)
102 rc = RegCreateKeyW(rootkey, net, key);
103 else
104 rc = RegOpenKeyW(rootkey, net, key);
106 return rc;
109 static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
111 UINT rc;
112 static const WCHAR URL[] = {'U','R','L',0};
114 if (create)
115 rc = RegCreateKeyW(rootkey, URL, key);
116 else
117 rc = RegOpenKeyW(rootkey, URL, key);
119 return rc;
123 static UINT find_given_source(HKEY key, LPCWSTR szSource, media_info *ss)
125 DWORD index = 0;
126 WCHAR szIndex[10];
127 DWORD size;
128 DWORD val_size;
129 LPWSTR val;
130 UINT rc = ERROR_SUCCESS;
132 while (rc == ERROR_SUCCESS)
134 val = NULL;
135 val_size = 0;
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,
141 &val_size);
142 if (lstrcmpiW(szSource,val)==0)
144 ss->path = val;
145 strcpyW(ss->szIndex,szIndex);
146 break;
148 else
149 strcpyW(ss->szIndex,szIndex);
151 HeapFree(GetProcessHeap(),0,val);
152 index ++;
155 return rc;
158 /******************************************************************
159 * MsiSourceListGetInfoW (MSI.@)
161 UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
162 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
163 LPCWSTR szProperty, LPWSTR szValue,
164 LPDWORD pcchValue)
166 HKEY sourcekey;
167 UINT rc;
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;
183 if (szUserSid)
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);
191 else
192 rc = OpenSourceKey(szProduct, &sourcekey, TRUE, FALSE);
194 if (rc != ERROR_SUCCESS)
195 return ERROR_UNKNOWN_PRODUCT;
197 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATH) == 0)
199 HKEY key;
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;
206 RegCloseKey(key);
208 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPT) ==0)
210 HKEY key;
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;
217 RegCloseKey(key);
219 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCE)==0)
221 LPWSTR buffer;
222 DWORD size = 0;
224 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0, 0, NULL,
225 &size);
226 if (size == 0)
227 rc = ERROR_UNKNOWN_PROPERTY;
228 else
230 LPWSTR ptr;
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,';');
236 if (!ptr)
237 rc = ERROR_UNKNOWN_PROPERTY;
238 else
240 ptr ++;
241 lstrcpynW(szValue, ptr, *pcchValue);
242 if (lstrlenW(ptr) > *pcchValue)
244 *pcchValue = lstrlenW(ptr)+1;
245 rc = ERROR_MORE_DATA;
247 else
248 rc = ERROR_SUCCESS;
250 HeapFree(GetProcessHeap(),0,buffer);
253 else if (strcmpW(INSTALLPROPERTY_LASTUSEDTYPE, szProperty)==0)
255 LPWSTR buffer;
256 DWORD size = 0;
258 RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0, 0, NULL,
259 &size);
260 if (size == 0)
261 rc = ERROR_UNKNOWN_PROPERTY;
262 else
264 buffer = HeapAlloc(GetProcessHeap(),0,size);
265 rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCE, 0,
266 0, (LPBYTE)buffer,&size);
267 if (*pcchValue < 1)
269 rc = ERROR_MORE_DATA;
270 *pcchValue = 1;
272 else
274 szValue[0] = buffer[0];
275 rc = ERROR_SUCCESS;
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;
287 else
289 FIXME("Unknown property %s\n",debugstr_w(szProperty));
290 rc = ERROR_UNKNOWN_PROPERTY;
293 RegCloseKey(sourcekey);
294 return rc;
297 /******************************************************************
298 * MsiSourceListSetInfoW (MSI.@)
300 UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
301 MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
302 LPCWSTR szProperty, LPCWSTR szValue)
304 HKEY sourcekey;
305 UINT rc;
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;
319 if (szUserSid)
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);
327 else
328 rc = OpenSourceKey(szProduct, &sourcekey, TRUE, TRUE);
330 if (rc != ERROR_SUCCESS)
331 return ERROR_UNKNOWN_PRODUCT;
334 if (strcmpW(szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATH) == 0)
336 HKEY key;
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;
344 RegCloseKey(key);
346 else if (strcmpW(szProperty, INSTALLPROPERTY_DISKPROMPT) ==0)
348 HKEY key;
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;
356 RegCloseKey(key);
358 else if (strcmpW(szProperty, INSTALLPROPERTY_LASTUSEDSOURCE)==0)
360 LPWSTR buffer = NULL;
361 DWORD size;
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)
370 typechar = 'n';
371 else if (dwOptions & MSISOURCETYPE_URL)
372 typechar = 'u';
373 else if (dwOptions & MSISOURCETYPE_MEDIA)
374 typechar = 'm';
375 else
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;
395 else
397 FIXME("Unknown property %s\n",debugstr_w(szProperty));
398 rc = ERROR_UNKNOWN_PROPERTY;
401 RegCloseKey(sourcekey);
402 return rc;
406 /******************************************************************
407 * MsiSourceListAddSourceExW (MSI.@)
409 UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
410 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource,
411 DWORD dwIndex)
413 HKEY sourcekey;
414 HKEY typekey;
415 UINT rc;
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),
420 dwIndex);
422 if (!szProduct)
423 return ERROR_INVALID_PARAMETER;
425 if (!szSource)
426 return ERROR_INVALID_PARAMETER;
428 if (dwOptions & MSICODE_PATCH)
430 FIXME("Unhandled options MSICODE_PATCH\n");
431 return ERROR_FUNCTION_FAILED;
434 if (szUserSid)
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);
442 else
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);
452 else
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");
467 else
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);
475 /* new source */
476 if (dwIndex > 0 && dwIndex < current_index)
477 FIXME("Need to reorder the souces! UNHANDLED\n");
479 current_index ++;
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);
487 return rc;
490 /******************************************************************
491 * MsiSourceListAddMediaDisk(MSI.@)
493 UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid,
494 MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId,
495 LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
497 HKEY sourcekey;
498 HKEY mediakey;
499 UINT rc;
500 WCHAR szIndex[10];
501 static const WCHAR fmt[] = {'%','i',0};
502 static const WCHAR disk_fmt[] = {'%','s',';','%','s',0};
503 static const WCHAR empty[1] = {0};
504 LPCWSTR pt1,pt2;
505 LPWSTR buffer;
506 DWORD size;
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;
521 if (szUserSid)
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);
529 else
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);
539 size = 2;
540 if (szVolumeLabel)
542 size +=lstrlenW(szVolumeLabel);
543 pt1 = szVolumeLabel;
545 else
546 pt1 = empty;
547 if (szDiskPrompt)
549 size +=lstrlenW(szDiskPrompt);
550 pt2 = szDiskPrompt;
552 else
553 pt2 = empty;
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;