ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

source.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2005 Aric Stewart for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 #define NONAMELESSUNION
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winreg.h"
00029 #include "winnls.h"
00030 #include "shlwapi.h"
00031 #include "wine/debug.h"
00032 #include "msi.h"
00033 #include "msiquery.h"
00034 #include "msipriv.h"
00035 #include "wincrypt.h"
00036 #include "winver.h"
00037 #include "winuser.h"
00038 #include "wine/unicode.h"
00039 #include "sddl.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00042 
00043 /*
00044  * These apis are defined in MSI 3.0
00045  */
00046 
00047 typedef struct tagMediaInfo
00048 {
00049     struct list entry;
00050     LPWSTR  path;
00051     WCHAR   szIndex[10];
00052     DWORD   index;
00053 } media_info;
00054 
00055 static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, DWORD dwOptions,
00056                           MSIINSTALLCONTEXT context, BOOL create)
00057 {
00058     HKEY rootkey = 0; 
00059     UINT rc = ERROR_FUNCTION_FAILED;
00060 
00061     if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
00062     {
00063         if (dwOptions & MSICODE_PATCH)
00064             rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
00065         else
00066             rc = MSIREG_OpenProductKey(szProduct, NULL, context,
00067                                        &rootkey, create);
00068     }
00069     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
00070     {
00071         if (dwOptions & MSICODE_PATCH)
00072             rc = MSIREG_OpenUserPatchesKey(szProduct, &rootkey, create);
00073         else
00074             rc = MSIREG_OpenProductKey(szProduct, NULL, context,
00075                                        &rootkey, create);
00076     }
00077     else if (context == MSIINSTALLCONTEXT_MACHINE)
00078     {
00079         if (dwOptions & MSICODE_PATCH)
00080             rc = MSIREG_OpenPatchesKey(szProduct, &rootkey, create);
00081         else
00082             rc = MSIREG_OpenProductKey(szProduct, NULL, context,
00083                                        &rootkey, create);
00084     }
00085 
00086     if (rc != ERROR_SUCCESS)
00087     {
00088         if (dwOptions & MSICODE_PATCH)
00089             return ERROR_UNKNOWN_PATCH;
00090         else
00091             return ERROR_UNKNOWN_PRODUCT;
00092     }
00093 
00094     if (create)
00095         rc = RegCreateKeyW(rootkey, szSourceList, key);
00096     else
00097     {
00098         rc = RegOpenKeyW(rootkey,szSourceList, key);
00099         if (rc != ERROR_SUCCESS)
00100             rc = ERROR_BAD_CONFIGURATION;
00101     }
00102 
00103     return rc;
00104 }
00105 
00106 static UINT OpenMediaSubkey(HKEY rootkey, HKEY *key, BOOL create)
00107 {
00108     UINT rc;
00109     static const WCHAR media[] = {'M','e','d','i','a',0};
00110 
00111     if (create)
00112         rc = RegCreateKeyW(rootkey, media, key);
00113     else
00114         rc = RegOpenKeyW(rootkey,media, key); 
00115 
00116     return rc;
00117 }
00118 
00119 static UINT OpenNetworkSubkey(HKEY rootkey, HKEY *key, BOOL create)
00120 {
00121     UINT rc;
00122     static const WCHAR net[] = {'N','e','t',0};
00123 
00124     if (create)
00125         rc = RegCreateKeyW(rootkey, net, key);
00126     else
00127         rc = RegOpenKeyW(rootkey, net, key); 
00128 
00129     return rc;
00130 }
00131 
00132 static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
00133 {
00134     UINT rc;
00135     static const WCHAR URL[] = {'U','R','L',0};
00136 
00137     if (create)
00138         rc = RegCreateKeyW(rootkey, URL, key);
00139     else
00140         rc = RegOpenKeyW(rootkey, URL, key); 
00141 
00142     return rc;
00143 }
00144 
00145 /******************************************************************
00146  *  MsiSourceListEnumMediaDisksA   (MSI.@)
00147  */
00148 UINT WINAPI MsiSourceListEnumMediaDisksA(LPCSTR szProductCodeOrPatchCode,
00149                                          LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext,
00150                                          DWORD dwOptions, DWORD dwIndex, LPDWORD pdwDiskId,
00151                                          LPSTR szVolumeLabel, LPDWORD pcchVolumeLabel,
00152                                          LPSTR szDiskPrompt, LPDWORD pcchDiskPrompt)
00153 {
00154     LPWSTR product = NULL;
00155     LPWSTR usersid = NULL;
00156     LPWSTR volume = NULL;
00157     LPWSTR prompt = NULL;
00158     UINT r = ERROR_INVALID_PARAMETER;
00159 
00160     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n", debugstr_a(szProductCodeOrPatchCode),
00161           debugstr_a(szUserSid), dwContext, dwOptions, dwIndex, pdwDiskId,
00162           szVolumeLabel, pcchVolumeLabel, szDiskPrompt, pcchDiskPrompt);
00163 
00164     if (szDiskPrompt && !pcchDiskPrompt)
00165         return ERROR_INVALID_PARAMETER;
00166 
00167     if (szProductCodeOrPatchCode) product = strdupAtoW(szProductCodeOrPatchCode);
00168     if (szUserSid) usersid = strdupAtoW(szUserSid);
00169 
00170     /* FIXME: add tests for an invalid format */
00171 
00172     if (pcchVolumeLabel)
00173         volume = msi_alloc(*pcchVolumeLabel * sizeof(WCHAR));
00174 
00175     if (pcchDiskPrompt)
00176         prompt = msi_alloc(*pcchDiskPrompt * sizeof(WCHAR));
00177 
00178     if (volume) *volume = '\0';
00179     if (prompt) *prompt = '\0';
00180     r = MsiSourceListEnumMediaDisksW(product, usersid, dwContext, dwOptions,
00181                                      dwIndex, pdwDiskId, volume, pcchVolumeLabel,
00182                                      prompt, pcchDiskPrompt);
00183     if (r != ERROR_SUCCESS)
00184         goto done;
00185 
00186     if (szVolumeLabel && pcchVolumeLabel)
00187         WideCharToMultiByte(CP_ACP, 0, volume, -1, szVolumeLabel,
00188                             *pcchVolumeLabel + 1, NULL, NULL);
00189 
00190     if (szDiskPrompt)
00191         WideCharToMultiByte(CP_ACP, 0, prompt, -1, szDiskPrompt,
00192                             *pcchDiskPrompt + 1, NULL, NULL);
00193 
00194 done:
00195     msi_free(product);
00196     msi_free(usersid);
00197     msi_free(volume);
00198     msi_free(prompt);
00199 
00200     return r;
00201 }
00202 
00203 /******************************************************************
00204  *  MsiSourceListEnumMediaDisksW   (MSI.@)
00205  */
00206 UINT WINAPI MsiSourceListEnumMediaDisksW(LPCWSTR szProductCodeOrPatchCode,
00207                                          LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
00208                                          DWORD dwOptions, DWORD dwIndex, LPDWORD pdwDiskId,
00209                                          LPWSTR szVolumeLabel, LPDWORD pcchVolumeLabel,
00210                                          LPWSTR szDiskPrompt, LPDWORD pcchDiskPrompt)
00211 {
00212     WCHAR squished_pc[GUID_SIZE];
00213     WCHAR convert[11];
00214     LPWSTR value = NULL;
00215     LPWSTR data = NULL;
00216     LPWSTR ptr, ptr2;
00217     HKEY source, media;
00218     DWORD valuesz, datasz = 0;
00219     DWORD type;
00220     DWORD numvals, size;
00221     LONG res;
00222     UINT r;
00223     static DWORD index = 0;
00224 
00225     static const WCHAR fmt[] = {'#','%','d',0};
00226 
00227     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p)\n", debugstr_w(szProductCodeOrPatchCode),
00228           debugstr_w(szUserSid), dwContext, dwOptions, dwIndex, szVolumeLabel,
00229           pcchVolumeLabel, szDiskPrompt, pcchDiskPrompt);
00230 
00231     if (!szProductCodeOrPatchCode ||
00232         !squash_guid(szProductCodeOrPatchCode, squished_pc))
00233         return ERROR_INVALID_PARAMETER;
00234 
00235     if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
00236         return ERROR_INVALID_PARAMETER;
00237 
00238     if (dwOptions != MSICODE_PRODUCT && dwOptions != MSICODE_PATCH)
00239         return ERROR_INVALID_PARAMETER;
00240 
00241     if (szDiskPrompt && !pcchDiskPrompt)
00242         return ERROR_INVALID_PARAMETER;
00243 
00244     if (dwIndex == 0)
00245         index = 0;
00246 
00247     if (dwIndex != index)
00248         return ERROR_INVALID_PARAMETER;
00249 
00250     r = OpenSourceKey(szProductCodeOrPatchCode, &source,
00251                       dwOptions, dwContext, FALSE);
00252     if (r != ERROR_SUCCESS)
00253         return r;
00254 
00255     r = OpenMediaSubkey(source, &media, FALSE);
00256     if (r != ERROR_SUCCESS)
00257     {
00258         RegCloseKey(source);
00259         return ERROR_NO_MORE_ITEMS;
00260     }
00261 
00262     if (!pcchVolumeLabel && !pcchDiskPrompt)
00263     {
00264         r = RegEnumValueW(media, dwIndex, NULL, NULL, NULL,
00265                           &type, NULL, NULL);
00266         goto done;
00267     }
00268 
00269     res = RegQueryInfoKeyW(media, NULL, NULL, NULL, NULL, NULL,
00270                            NULL, &numvals, &valuesz, &datasz, NULL, NULL);
00271     if (res != ERROR_SUCCESS)
00272     {
00273         r = ERROR_BAD_CONFIGURATION;
00274         goto done;
00275     }
00276 
00277     value = msi_alloc(++valuesz * sizeof(WCHAR));
00278     data = msi_alloc(++datasz * sizeof(WCHAR));
00279     if (!value || !data)
00280     {
00281         r = ERROR_OUTOFMEMORY;
00282         goto done;
00283     }
00284 
00285     r = RegEnumValueW(media, dwIndex, value, &valuesz,
00286                       NULL, &type, (LPBYTE)data, &datasz);
00287     if (r != ERROR_SUCCESS)
00288         goto done;
00289 
00290     if (pdwDiskId)
00291         *pdwDiskId = atolW(value);
00292 
00293     ptr2 = data;
00294     ptr = strchrW(data, ';');
00295     if (!ptr)
00296         ptr = data;
00297     else
00298         *ptr = '\0';
00299 
00300     if (pcchVolumeLabel)
00301     {
00302         if (type == REG_DWORD)
00303         {
00304             sprintfW(convert, fmt, *data);
00305             size = lstrlenW(convert);
00306             ptr2 = convert;
00307         }
00308         else
00309             size = lstrlenW(data);
00310 
00311         if (size >= *pcchVolumeLabel)
00312             r = ERROR_MORE_DATA;
00313         else if (szVolumeLabel)
00314             lstrcpyW(szVolumeLabel, ptr2);
00315 
00316         *pcchVolumeLabel = size;
00317     }
00318 
00319     if (pcchDiskPrompt)
00320     {
00321         if (!*ptr)
00322             ptr++;
00323 
00324         if (type == REG_DWORD)
00325         {
00326             sprintfW(convert, fmt, *ptr);
00327             size = lstrlenW(convert);
00328             ptr = convert;
00329         }
00330         else
00331             size = lstrlenW(ptr);
00332 
00333         if (size >= *pcchDiskPrompt)
00334             r = ERROR_MORE_DATA;
00335         else if (szDiskPrompt)
00336             lstrcpyW(szDiskPrompt, ptr);
00337 
00338         *pcchDiskPrompt = size;
00339     }
00340 
00341     index++;
00342 
00343 done:
00344     msi_free(value);
00345     msi_free(data);
00346     RegCloseKey(source);
00347 
00348     return r;
00349 }
00350 
00351 /******************************************************************
00352  *  MsiSourceListEnumSourcesA   (MSI.@)
00353  */
00354 UINT WINAPI MsiSourceListEnumSourcesA(LPCSTR szProductCodeOrPatch, LPCSTR szUserSid,
00355                                       MSIINSTALLCONTEXT dwContext,
00356                                       DWORD dwOptions, DWORD dwIndex,
00357                                       LPSTR szSource, LPDWORD pcchSource)
00358 {
00359     LPWSTR product = NULL;
00360     LPWSTR usersid = NULL;
00361     LPWSTR source = NULL;
00362     DWORD len = 0;
00363     UINT r = ERROR_INVALID_PARAMETER;
00364     static DWORD index = 0;
00365 
00366     TRACE("(%s, %s, %d, %d, %d, %p, %p)\n", debugstr_a(szProductCodeOrPatch),
00367           debugstr_a(szUserSid), dwContext, dwOptions, dwIndex, szSource, pcchSource);
00368 
00369     if (dwIndex == 0)
00370         index = 0;
00371 
00372     if (szSource && !pcchSource)
00373         goto done;
00374 
00375     if (dwIndex != index)
00376         goto done;
00377 
00378     if (szProductCodeOrPatch) product = strdupAtoW(szProductCodeOrPatch);
00379     if (szUserSid) usersid = strdupAtoW(szUserSid);
00380 
00381     r = MsiSourceListEnumSourcesW(product, usersid, dwContext, dwOptions,
00382                                   dwIndex, NULL, &len);
00383     if (r != ERROR_SUCCESS)
00384         goto done;
00385 
00386     source = msi_alloc(++len * sizeof(WCHAR));
00387     if (!source)
00388     {
00389         r = ERROR_OUTOFMEMORY;
00390         goto done;
00391     }
00392 
00393     *source = '\0';
00394     r = MsiSourceListEnumSourcesW(product, usersid, dwContext, dwOptions,
00395                                   dwIndex, source, &len);
00396     if (r != ERROR_SUCCESS)
00397         goto done;
00398 
00399     len = WideCharToMultiByte(CP_ACP, 0, source, -1, NULL, 0, NULL, NULL);
00400     if (pcchSource && *pcchSource >= len)
00401         WideCharToMultiByte(CP_ACP, 0, source, -1, szSource, len, NULL, NULL);
00402     else if (szSource)
00403         r = ERROR_MORE_DATA;
00404 
00405     if (pcchSource)
00406         *pcchSource = len - 1;
00407 
00408 done:
00409     msi_free(product);
00410     msi_free(usersid);
00411     msi_free(source);
00412 
00413     if (r == ERROR_SUCCESS)
00414     {
00415         if (szSource || !pcchSource) index++;
00416     }
00417     else if (dwIndex > index)
00418         index = 0;
00419 
00420     return r;
00421 }
00422 
00423 /******************************************************************
00424  *  MsiSourceListEnumSourcesW   (MSI.@)
00425  */
00426 UINT WINAPI MsiSourceListEnumSourcesW(LPCWSTR szProductCodeOrPatch, LPCWSTR szUserSid,
00427                                       MSIINSTALLCONTEXT dwContext,
00428                                       DWORD dwOptions, DWORD dwIndex,
00429                                       LPWSTR szSource, LPDWORD pcchSource)
00430 {
00431     WCHAR squished_pc[GUID_SIZE];
00432     WCHAR name[32];
00433     HKEY source = NULL;
00434     HKEY subkey = NULL;
00435     LONG res;
00436     UINT r = ERROR_INVALID_PARAMETER;
00437     static DWORD index = 0;
00438 
00439     static const WCHAR format[] = {'%','d',0};
00440 
00441     TRACE("(%s, %s, %d, %d, %d, %p, %p)\n", debugstr_w(szProductCodeOrPatch),
00442           debugstr_w(szUserSid), dwContext, dwOptions, dwIndex, szSource, pcchSource);
00443 
00444     if (dwIndex == 0)
00445         index = 0;
00446 
00447     if (!szProductCodeOrPatch || !squash_guid(szProductCodeOrPatch, squished_pc))
00448         goto done;
00449 
00450     if (szSource && !pcchSource)
00451         goto done;
00452 
00453     if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
00454         goto done;
00455 
00456     if ((dwOptions & MSISOURCETYPE_NETWORK) && (dwOptions & MSISOURCETYPE_URL))
00457         goto done;
00458 
00459     if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
00460         goto done;
00461 
00462     if (dwIndex != index)
00463         goto done;
00464 
00465     r = OpenSourceKey(szProductCodeOrPatch, &source,
00466                       dwOptions, dwContext, FALSE);
00467     if (r != ERROR_SUCCESS)
00468         goto done;
00469 
00470     if (dwOptions & MSISOURCETYPE_NETWORK)
00471         r = OpenNetworkSubkey(source, &subkey, FALSE);
00472     else if (dwOptions & MSISOURCETYPE_URL)
00473         r = OpenURLSubkey(source, &subkey, FALSE);
00474 
00475     if (r != ERROR_SUCCESS)
00476     {
00477         r = ERROR_NO_MORE_ITEMS;
00478         goto done;
00479     }
00480 
00481     sprintfW(name, format, dwIndex + 1);
00482 
00483     res = RegQueryValueExW(subkey, name, 0, 0, (LPBYTE)szSource, pcchSource);
00484     if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
00485         r = ERROR_NO_MORE_ITEMS;
00486 
00487 done:
00488     RegCloseKey(subkey);
00489     RegCloseKey(source);
00490 
00491     if (r == ERROR_SUCCESS)
00492     {
00493         if (szSource || !pcchSource) index++;
00494     }
00495     else if (dwIndex > index)
00496         index = 0;
00497 
00498     return r;
00499 }
00500 
00501 /******************************************************************
00502  *  MsiSourceListGetInfoA   (MSI.@)
00503  */
00504 UINT WINAPI MsiSourceListGetInfoA( LPCSTR szProduct, LPCSTR szUserSid,
00505                                    MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
00506                                    LPCSTR szProperty, LPSTR szValue,
00507                                    LPDWORD pcchValue)
00508 {
00509     UINT ret;
00510     LPWSTR product = NULL;
00511     LPWSTR usersid = NULL;
00512     LPWSTR property = NULL;
00513     LPWSTR value = NULL;
00514     DWORD len = 0;
00515 
00516     if (szValue && !pcchValue)
00517         return ERROR_INVALID_PARAMETER;
00518 
00519     if (szProduct) product = strdupAtoW(szProduct);
00520     if (szUserSid) usersid = strdupAtoW(szUserSid);
00521     if (szProperty) property = strdupAtoW(szProperty);
00522 
00523     ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
00524                                 property, NULL, &len);
00525     if (ret != ERROR_SUCCESS)
00526         goto done;
00527 
00528     value = msi_alloc(++len * sizeof(WCHAR));
00529     if (!value)
00530         return ERROR_OUTOFMEMORY;
00531 
00532     *value = '\0';
00533     ret = MsiSourceListGetInfoW(product, usersid, dwContext, dwOptions,
00534                                 property, value, &len);
00535     if (ret != ERROR_SUCCESS)
00536         goto done;
00537 
00538     len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL);
00539     if (*pcchValue >= len)
00540         WideCharToMultiByte(CP_ACP, 0, value, -1, szValue, len, NULL, NULL);
00541     else if (szValue)
00542         ret = ERROR_MORE_DATA;
00543 
00544     *pcchValue = len - 1;
00545 
00546 done:
00547     msi_free(product);
00548     msi_free(usersid);
00549     msi_free(property);
00550     msi_free(value);
00551     return ret;
00552 }
00553 
00554 /******************************************************************
00555  *  MsiSourceListGetInfoW   (MSI.@)
00556  */
00557 UINT WINAPI MsiSourceListGetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
00558                                    MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
00559                                    LPCWSTR szProperty, LPWSTR szValue, 
00560                                    LPDWORD pcchValue) 
00561 {
00562     WCHAR squished_pc[GUID_SIZE];
00563     HKEY sourcekey, media;
00564     LPWSTR source, ptr;
00565     DWORD size;
00566     UINT rc;
00567 
00568     static const WCHAR mediapack[] = {
00569         'M','e','d','i','a','P','a','c','k','a','g','e',0};
00570 
00571     TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szProperty));
00572 
00573     if (!szProduct || !squash_guid(szProduct, squished_pc))
00574         return ERROR_INVALID_PARAMETER;
00575 
00576     if (szValue && !pcchValue)
00577         return ERROR_INVALID_PARAMETER;
00578 
00579     if (dwContext != MSIINSTALLCONTEXT_USERMANAGED &&
00580         dwContext != MSIINSTALLCONTEXT_USERUNMANAGED &&
00581         dwContext != MSIINSTALLCONTEXT_MACHINE)
00582         return ERROR_INVALID_PARAMETER;
00583 
00584     if (!szProperty)
00585         return ERROR_INVALID_PARAMETER;
00586 
00587     if (szUserSid)
00588         FIXME("Unhandled UserSid %s\n",debugstr_w(szUserSid));
00589 
00590     rc = OpenSourceKey(szProduct, &sourcekey, dwOptions, dwContext, FALSE);
00591     if (rc != ERROR_SUCCESS)
00592         return rc;
00593 
00594     if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
00595         !strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
00596     {
00597         rc = OpenMediaSubkey(sourcekey, &media, FALSE);
00598         if (rc != ERROR_SUCCESS)
00599         {
00600             RegCloseKey(sourcekey);
00601             return ERROR_SUCCESS;
00602         }
00603 
00604         if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
00605             szProperty = mediapack;
00606 
00607         RegQueryValueExW(media, szProperty, 0, 0, (LPBYTE)szValue, pcchValue);
00608         RegCloseKey(media);
00609     }
00610     else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) ||
00611              !strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
00612     {
00613         rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
00614                               0, 0, NULL, &size);
00615         if (rc != ERROR_SUCCESS)
00616         {
00617             RegCloseKey(sourcekey);
00618             return ERROR_SUCCESS;
00619         }
00620 
00621         source = msi_alloc(size);
00622         RegQueryValueExW(sourcekey, INSTALLPROPERTY_LASTUSEDSOURCEW,
00623                          0, 0, (LPBYTE)source, &size);
00624 
00625         if (!*source)
00626         {
00627             msi_free(source);
00628             RegCloseKey(sourcekey);
00629             return ERROR_SUCCESS;
00630         }
00631 
00632         if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDTYPEW ))
00633         {
00634             if (*source != 'n' && *source != 'u' && *source != 'm')
00635             {
00636                 msi_free(source);
00637                 RegCloseKey(sourcekey);
00638                 return ERROR_SUCCESS;
00639             }
00640 
00641             ptr = source;
00642             source[1] = '\0';
00643         }
00644         else
00645         {
00646             ptr = strrchrW(source, ';');
00647             if (!ptr)
00648                 ptr = source;
00649             else
00650                 ptr++;
00651         }
00652 
00653         if (szValue)
00654         {
00655             if (strlenW(ptr) < *pcchValue)
00656                 lstrcpyW(szValue, ptr);
00657             else
00658                 rc = ERROR_MORE_DATA;
00659         }
00660 
00661         *pcchValue = lstrlenW(ptr);
00662         msi_free(source);
00663     }
00664     else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
00665     {
00666         *pcchValue = *pcchValue * sizeof(WCHAR);
00667         rc = RegQueryValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0, 0,
00668                               (LPBYTE)szValue, pcchValue);
00669         if (rc != ERROR_SUCCESS && rc != ERROR_MORE_DATA)
00670         {
00671             *pcchValue = 0;
00672             rc = ERROR_SUCCESS;
00673         }
00674         else
00675         {
00676             if (*pcchValue)
00677                 *pcchValue = (*pcchValue - 1) / sizeof(WCHAR);
00678             if (szValue)
00679                 szValue[*pcchValue] = '\0';
00680         }
00681     }
00682     else
00683     {
00684         FIXME("Unknown property %s\n",debugstr_w(szProperty));
00685         rc = ERROR_UNKNOWN_PROPERTY;
00686     }
00687 
00688     RegCloseKey(sourcekey);
00689     return rc;
00690 }
00691 
00692 /******************************************************************
00693  *  MsiSourceListSetInfoA   (MSI.@)
00694  */
00695 UINT WINAPI MsiSourceListSetInfoA(LPCSTR szProduct, LPCSTR szUserSid,
00696                                   MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
00697                                   LPCSTR szProperty, LPCSTR szValue)
00698 {
00699     UINT ret;
00700     LPWSTR product = NULL;
00701     LPWSTR usersid = NULL;
00702     LPWSTR property = NULL;
00703     LPWSTR value = NULL;
00704 
00705     if (szProduct) product = strdupAtoW(szProduct);
00706     if (szUserSid) usersid = strdupAtoW(szUserSid);
00707     if (szProperty) property = strdupAtoW(szProperty);
00708     if (szValue) value = strdupAtoW(szValue);
00709 
00710     ret = MsiSourceListSetInfoW(product, usersid, dwContext, dwOptions,
00711                                 property, value);
00712 
00713     msi_free(product);
00714     msi_free(usersid);
00715     msi_free(property);
00716     msi_free(value);
00717 
00718     return ret;
00719 }
00720 
00721 UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
00722                               MSIINSTALLCONTEXT context, DWORD options,
00723                               LPCWSTR value)
00724 {
00725     HKEY source;
00726     LPWSTR buffer;
00727     WCHAR typechar;
00728     DWORD size;
00729     UINT r;
00730     int index = 1;
00731 
00732     static const WCHAR format[] = {'%','c',';','%','i',';','%','s',0};
00733 
00734     if (options & MSISOURCETYPE_NETWORK)
00735         typechar = 'n';
00736     else if (options & MSISOURCETYPE_URL)
00737         typechar = 'u';
00738     else if (options & MSISOURCETYPE_MEDIA)
00739         typechar = 'm';
00740     else
00741         return ERROR_INVALID_PARAMETER;
00742 
00743     if (!(options & MSISOURCETYPE_MEDIA))
00744     {
00745         r = MsiSourceListAddSourceExW(product, usersid, context,
00746                                       options, value, 0);
00747         if (r != ERROR_SUCCESS)
00748             return r;
00749 
00750         index = 0;
00751         while ((r = MsiSourceListEnumSourcesW(product, usersid, context, options,
00752                                               index, NULL, NULL)) == ERROR_SUCCESS)
00753             index++;
00754 
00755         if (r != ERROR_NO_MORE_ITEMS)
00756             return r;
00757     }
00758 
00759     size = (lstrlenW(format) + lstrlenW(value) + 7) * sizeof(WCHAR);
00760     buffer = msi_alloc(size);
00761     if (!buffer)
00762         return ERROR_OUTOFMEMORY;
00763 
00764     r = OpenSourceKey(product, &source, MSICODE_PRODUCT, context, FALSE);
00765     if (r != ERROR_SUCCESS)
00766         return r;
00767 
00768     sprintfW(buffer, format, typechar, index, value);
00769 
00770     size = (lstrlenW(buffer) + 1) * sizeof(WCHAR);
00771     r = RegSetValueExW(source, INSTALLPROPERTY_LASTUSEDSOURCEW, 0,
00772                        REG_SZ, (LPBYTE)buffer, size);
00773     msi_free(buffer);
00774 
00775     RegCloseKey(source);
00776     return r;
00777 }
00778 
00779 /******************************************************************
00780  *  MsiSourceListSetInfoW   (MSI.@)
00781  */
00782 UINT WINAPI MsiSourceListSetInfoW( LPCWSTR szProduct, LPCWSTR szUserSid,
00783                                    MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
00784                                    LPCWSTR szProperty, LPCWSTR szValue)
00785 {
00786     WCHAR squished_pc[GUID_SIZE];
00787     HKEY sourcekey, media;
00788     LPCWSTR property;
00789     UINT rc;
00790 
00791     static const WCHAR media_package[] = {
00792         'M','e','d','i','a','P','a','c','k','a','g','e',0
00793     };
00794 
00795     TRACE("%s %s %x %x %s %s\n", debugstr_w(szProduct), debugstr_w(szUserSid),
00796             dwContext, dwOptions, debugstr_w(szProperty), debugstr_w(szValue));
00797 
00798     if (!szProduct || !squash_guid(szProduct, squished_pc))
00799         return ERROR_INVALID_PARAMETER;
00800 
00801     if (!szProperty)
00802         return ERROR_INVALID_PARAMETER;
00803 
00804     if (!szValue)
00805         return ERROR_UNKNOWN_PROPERTY;
00806 
00807     if (dwContext == MSIINSTALLCONTEXT_MACHINE && szUserSid)
00808         return ERROR_INVALID_PARAMETER;
00809 
00810     if (dwOptions & MSICODE_PATCH)
00811     {
00812         FIXME("Unhandled options MSICODE_PATCH\n");
00813         return ERROR_UNKNOWN_PATCH;
00814     }
00815 
00816     property = szProperty;
00817     if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ))
00818         property = media_package;
00819 
00820     rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
00821     if (rc != ERROR_SUCCESS)
00822         return rc;
00823 
00824     if (strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ) &&
00825         dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL))
00826     {
00827         RegCloseKey(sourcekey);
00828         return ERROR_INVALID_PARAMETER;
00829     }
00830 
00831     if (!strcmpW( szProperty, INSTALLPROPERTY_MEDIAPACKAGEPATHW ) ||
00832         !strcmpW( szProperty, INSTALLPROPERTY_DISKPROMPTW ))
00833     {
00834         rc = OpenMediaSubkey(sourcekey, &media, TRUE);
00835         if (rc == ERROR_SUCCESS)
00836         {
00837             rc = msi_reg_set_val_str(media, property, szValue);
00838             RegCloseKey(media);
00839         }
00840     }
00841     else if (!strcmpW( szProperty, INSTALLPROPERTY_PACKAGENAMEW ))
00842     {
00843         DWORD size = (lstrlenW(szValue) + 1) * sizeof(WCHAR);
00844         rc = RegSetValueExW(sourcekey, INSTALLPROPERTY_PACKAGENAMEW, 0,
00845                 REG_SZ, (const BYTE *)szValue, size);
00846         if (rc != ERROR_SUCCESS)
00847             rc = ERROR_UNKNOWN_PROPERTY;
00848     }
00849     else if (!strcmpW( szProperty, INSTALLPROPERTY_LASTUSEDSOURCEW ))
00850     {
00851         if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
00852             rc = ERROR_INVALID_PARAMETER;
00853         else
00854             rc = msi_set_last_used_source(szProduct, szUserSid, dwContext,
00855                                           dwOptions, szValue);
00856     }
00857     else
00858         rc = ERROR_UNKNOWN_PROPERTY;
00859 
00860     RegCloseKey(sourcekey);
00861     return rc;
00862 }
00863 
00864 /******************************************************************
00865  *  MsiSourceListAddSourceW (MSI.@)
00866  */
00867 UINT WINAPI MsiSourceListAddSourceW( LPCWSTR szProduct, LPCWSTR szUserName,
00868         DWORD dwReserved, LPCWSTR szSource)
00869 {
00870     WCHAR squished_pc[GUID_SIZE];
00871     INT ret;
00872     LPWSTR sidstr = NULL;
00873     DWORD sidsize = 0;
00874     DWORD domsize = 0;
00875     DWORD context;
00876     HKEY hkey = 0;
00877     UINT r;
00878 
00879     TRACE("%s %s %s\n", debugstr_w(szProduct), debugstr_w(szUserName), debugstr_w(szSource));
00880 
00881     if (!szSource || !*szSource)
00882         return ERROR_INVALID_PARAMETER;
00883 
00884     if (dwReserved != 0)
00885         return ERROR_INVALID_PARAMETER;
00886 
00887     if (!szProduct || !squash_guid(szProduct, squished_pc))
00888         return ERROR_INVALID_PARAMETER;
00889 
00890     if (!szUserName || !*szUserName)
00891         context = MSIINSTALLCONTEXT_MACHINE;
00892     else
00893     {
00894         if (LookupAccountNameW(NULL, szUserName, NULL, &sidsize, NULL, &domsize, NULL))
00895         {
00896             PSID psid = msi_alloc(sidsize);
00897 
00898             if (LookupAccountNameW(NULL, szUserName, psid, &sidsize, NULL, &domsize, NULL))
00899                 ConvertSidToStringSidW(psid, &sidstr);
00900 
00901             msi_free(psid);
00902         }
00903 
00904         r = MSIREG_OpenProductKey(szProduct, NULL,
00905                                   MSIINSTALLCONTEXT_USERMANAGED, &hkey, FALSE);
00906         if (r == ERROR_SUCCESS)
00907             context = MSIINSTALLCONTEXT_USERMANAGED;
00908         else
00909         {
00910             r = MSIREG_OpenProductKey(szProduct, NULL,
00911                                       MSIINSTALLCONTEXT_USERUNMANAGED,
00912                                       &hkey, FALSE);
00913             if (r != ERROR_SUCCESS)
00914                 return ERROR_UNKNOWN_PRODUCT;
00915 
00916             context = MSIINSTALLCONTEXT_USERUNMANAGED;
00917         }
00918 
00919         RegCloseKey(hkey);
00920     }
00921 
00922     ret = MsiSourceListAddSourceExW(szProduct, sidstr, 
00923         context, MSISOURCETYPE_NETWORK, szSource, 0);
00924 
00925     if (sidstr)
00926         LocalFree(sidstr);
00927 
00928     return ret;
00929 }
00930 
00931 /******************************************************************
00932  *  MsiSourceListAddSourceA (MSI.@)
00933  */
00934 UINT WINAPI MsiSourceListAddSourceA( LPCSTR szProduct, LPCSTR szUserName,
00935         DWORD dwReserved, LPCSTR szSource)
00936 {
00937     INT ret;
00938     LPWSTR szwproduct;
00939     LPWSTR szwusername;
00940     LPWSTR szwsource;
00941 
00942     szwproduct = strdupAtoW( szProduct );
00943     szwusername = strdupAtoW( szUserName );
00944     szwsource = strdupAtoW( szSource );
00945 
00946     ret = MsiSourceListAddSourceW(szwproduct, szwusername, dwReserved, szwsource);
00947 
00948     msi_free(szwproduct);
00949     msi_free(szwusername);
00950     msi_free(szwsource);
00951 
00952     return ret;
00953 }
00954 
00955 /******************************************************************
00956  *  MsiSourceListAddSourceExA (MSI.@)
00957  */
00958 UINT WINAPI MsiSourceListAddSourceExA(LPCSTR szProduct, LPCSTR szUserSid,
00959         MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szSource, DWORD dwIndex)
00960 {
00961     UINT ret;
00962     LPWSTR product, usersid, source;
00963 
00964     product = strdupAtoW(szProduct);
00965     usersid = strdupAtoW(szUserSid);
00966     source = strdupAtoW(szSource);
00967 
00968     ret = MsiSourceListAddSourceExW(product, usersid, dwContext,
00969                                     dwOptions, source, dwIndex);
00970 
00971     msi_free(product);
00972     msi_free(usersid);
00973     msi_free(source);
00974 
00975     return ret;
00976 }
00977 
00978 static void free_source_list(struct list *sourcelist)
00979 {
00980     while (!list_empty(sourcelist))
00981     {
00982         media_info *info = LIST_ENTRY(list_head(sourcelist), media_info, entry);
00983         list_remove(&info->entry);
00984         msi_free(info->path);
00985         msi_free(info);
00986     }
00987 }
00988 
00989 static void add_source_to_list(struct list *sourcelist, media_info *info,
00990                                DWORD *index)
00991 {
00992     media_info *iter;
00993     BOOL found = FALSE;
00994     static const WCHAR fmt[] = {'%','i',0};
00995 
00996     if (index) *index = 0;
00997 
00998     if (list_empty(sourcelist))
00999     {
01000         list_add_head(sourcelist, &info->entry);
01001         return;
01002     }
01003 
01004     LIST_FOR_EACH_ENTRY(iter, sourcelist, media_info, entry)
01005     {
01006         if (!found && info->index < iter->index)
01007         {
01008             found = TRUE;
01009             list_add_before(&iter->entry, &info->entry);
01010         }
01011 
01012         /* update the rest of the list */
01013         if (found)
01014             sprintfW(iter->szIndex, fmt, ++iter->index);
01015         else if (index)
01016             (*index)++;
01017     }
01018 
01019     if (!found)
01020         list_add_after(&iter->entry, &info->entry);
01021 }
01022 
01023 static UINT fill_source_list(struct list *sourcelist, HKEY sourcekey, DWORD *count)
01024 {
01025     UINT r = ERROR_SUCCESS;
01026     DWORD index = 0;
01027     WCHAR name[10];
01028     DWORD size, val_size;
01029     media_info *entry;
01030 
01031     *count = 0;
01032 
01033     while (r == ERROR_SUCCESS)
01034     {
01035         size = sizeof(name) / sizeof(name[0]);
01036         r = RegEnumValueW(sourcekey, index, name, &size, NULL, NULL, NULL, &val_size);
01037         if (r != ERROR_SUCCESS)
01038             return r;
01039 
01040         entry = msi_alloc(sizeof(media_info));
01041         if (!entry)
01042             goto error;
01043 
01044         entry->path = msi_alloc(val_size);
01045         if (!entry->path)
01046         {
01047             msi_free(entry);
01048             goto error;
01049         }
01050 
01051         lstrcpyW(entry->szIndex, name);
01052         entry->index = atoiW(name);
01053 
01054         size++;
01055         r = RegEnumValueW(sourcekey, index, name, &size, NULL,
01056                           NULL, (LPBYTE)entry->path, &val_size);
01057         if (r != ERROR_SUCCESS)
01058         {
01059             msi_free(entry->path);
01060             msi_free(entry);
01061             goto error;
01062         }
01063 
01064         index = ++(*count);
01065         add_source_to_list(sourcelist, entry, NULL);
01066     }
01067 
01068 error:
01069     *count = -1;
01070     free_source_list(sourcelist);
01071     return ERROR_OUTOFMEMORY;
01072 }
01073 
01074 /******************************************************************
01075  *  MsiSourceListAddSourceExW (MSI.@)
01076  */
01077 UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
01078         MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCWSTR szSource, 
01079         DWORD dwIndex)
01080 {
01081     HKEY sourcekey;
01082     HKEY typekey;
01083     UINT rc;
01084     struct list sourcelist;
01085     media_info *info;
01086     WCHAR squished_pc[GUID_SIZE];
01087     WCHAR name[10];
01088     LPWSTR source;
01089     LPCWSTR postfix;
01090     DWORD size, count;
01091     DWORD index;
01092 
01093     static const WCHAR fmt[] = {'%','i',0};
01094 
01095     TRACE("%s %s %x %x %s %i\n", debugstr_w(szProduct), debugstr_w(szUserSid),
01096           dwContext, dwOptions, debugstr_w(szSource), dwIndex);
01097 
01098     if (!szProduct || !squash_guid(szProduct, squished_pc))
01099         return ERROR_INVALID_PARAMETER;
01100 
01101     if (!szSource || !*szSource)
01102         return ERROR_INVALID_PARAMETER;
01103 
01104     if (!(dwOptions & (MSISOURCETYPE_NETWORK | MSISOURCETYPE_URL)))
01105         return ERROR_INVALID_PARAMETER;
01106 
01107     if (dwOptions & MSICODE_PATCH)
01108     {
01109         FIXME("Unhandled options MSICODE_PATCH\n");
01110         return ERROR_FUNCTION_FAILED;
01111     }
01112 
01113     if (szUserSid && (dwContext & MSIINSTALLCONTEXT_MACHINE))
01114         return ERROR_INVALID_PARAMETER;
01115 
01116     rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
01117     if (rc != ERROR_SUCCESS)
01118         return rc;
01119 
01120     if (dwOptions & MSISOURCETYPE_NETWORK)
01121         rc = OpenNetworkSubkey(sourcekey, &typekey, TRUE);
01122     else if (dwOptions & MSISOURCETYPE_URL)
01123         rc = OpenURLSubkey(sourcekey, &typekey, TRUE);
01124     else if (dwOptions & MSISOURCETYPE_MEDIA)
01125         rc = OpenMediaSubkey(sourcekey, &typekey, TRUE);
01126     else
01127     {
01128         ERR("unknown media type: %08x\n", dwOptions);
01129         RegCloseKey(sourcekey);
01130         return ERROR_FUNCTION_FAILED;
01131     }
01132     if (rc != ERROR_SUCCESS)
01133     {
01134         ERR("can't open subkey %u\n", rc);
01135         RegCloseKey(sourcekey);
01136         return rc;
01137     }
01138 
01139     postfix = (dwOptions & MSISOURCETYPE_NETWORK) ? szBackSlash : szForwardSlash;
01140     if (szSource[lstrlenW(szSource) - 1] == *postfix)
01141         source = strdupW(szSource);
01142     else
01143     {
01144         size = lstrlenW(szSource) + 2;
01145         source = msi_alloc(size * sizeof(WCHAR));
01146         lstrcpyW(source, szSource);
01147         lstrcatW(source, postfix);
01148     }
01149 
01150     list_init(&sourcelist);
01151     rc = fill_source_list(&sourcelist, typekey, &count);
01152     if (rc != ERROR_NO_MORE_ITEMS)
01153         return rc;
01154 
01155     size = (lstrlenW(source) + 1) * sizeof(WCHAR);
01156 
01157     if (count == 0)
01158     {
01159         rc = RegSetValueExW(typekey, szOne, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
01160         goto done;
01161     }
01162     else if (dwIndex > count || dwIndex == 0)
01163     {
01164         sprintfW(name, fmt, count + 1);
01165         rc = RegSetValueExW(typekey, name, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
01166         goto done;
01167     }
01168     else
01169     {
01170         sprintfW(name, fmt, dwIndex);
01171         info = msi_alloc(sizeof(media_info));
01172         if (!info)
01173         {
01174             rc = ERROR_OUTOFMEMORY;
01175             goto done;
01176         }
01177 
01178         info->path = strdupW(source);
01179         lstrcpyW(info->szIndex, name);
01180         info->index = dwIndex;
01181         add_source_to_list(&sourcelist, info, &index);
01182 
01183         LIST_FOR_EACH_ENTRY(info, &sourcelist, media_info, entry)
01184         {
01185             if (info->index < index)
01186                 continue;
01187 
01188             size = (lstrlenW(info->path) + 1) * sizeof(WCHAR);
01189             rc = RegSetValueExW(typekey, info->szIndex, 0,
01190                                 REG_EXPAND_SZ, (LPBYTE)info->path, size);
01191             if (rc != ERROR_SUCCESS)
01192                 goto done;
01193         }
01194     }
01195 
01196 done:
01197     free_source_list(&sourcelist);
01198     msi_free(source);
01199     RegCloseKey(typekey);
01200     RegCloseKey(sourcekey);
01201     return rc;
01202 }
01203 
01204 /******************************************************************
01205  *  MsiSourceListAddMediaDiskA (MSI.@)
01206  */
01207 UINT WINAPI MsiSourceListAddMediaDiskA(LPCSTR szProduct, LPCSTR szUserSid,
01208         MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId,
01209         LPCSTR szVolumeLabel, LPCSTR szDiskPrompt)
01210 {
01211     UINT r;
01212     LPWSTR product = NULL;
01213     LPWSTR usersid = NULL;
01214     LPWSTR volume = NULL;
01215     LPWSTR prompt = NULL;
01216 
01217     if (szProduct) product = strdupAtoW(szProduct);
01218     if (szUserSid) usersid = strdupAtoW(szUserSid);
01219     if (szVolumeLabel) volume = strdupAtoW(szVolumeLabel);
01220     if (szDiskPrompt) prompt = strdupAtoW(szDiskPrompt);
01221 
01222     r = MsiSourceListAddMediaDiskW(product, usersid, dwContext, dwOptions,
01223                                      dwDiskId, volume, prompt);
01224 
01225     msi_free(product);
01226     msi_free(usersid);
01227     msi_free(volume);
01228     msi_free(prompt);
01229 
01230     return r;
01231 }
01232 
01233 /******************************************************************
01234  *  MsiSourceListAddMediaDiskW (MSI.@)
01235  */
01236 UINT WINAPI MsiSourceListAddMediaDiskW(LPCWSTR szProduct, LPCWSTR szUserSid, 
01237         MSIINSTALLCONTEXT dwContext, DWORD dwOptions, DWORD dwDiskId, 
01238         LPCWSTR szVolumeLabel, LPCWSTR szDiskPrompt)
01239 {
01240     HKEY sourcekey;
01241     HKEY mediakey;
01242     UINT rc;
01243     WCHAR szIndex[10];
01244     WCHAR squished_pc[GUID_SIZE];
01245     LPWSTR buffer;
01246     DWORD size;
01247 
01248     static const WCHAR fmt[] = {'%','i',0};
01249 
01250     TRACE("%s %s %x %x %i %s %s\n", debugstr_w(szProduct),
01251             debugstr_w(szUserSid), dwContext, dwOptions, dwDiskId,
01252             debugstr_w(szVolumeLabel), debugstr_w(szDiskPrompt));
01253 
01254     if (!szProduct || !squash_guid(szProduct, squished_pc))
01255         return ERROR_INVALID_PARAMETER;
01256 
01257     if (dwOptions != MSICODE_PRODUCT && dwOptions != MSICODE_PATCH)
01258         return ERROR_INVALID_PARAMETER;
01259 
01260     if ((szVolumeLabel && !*szVolumeLabel) || (szDiskPrompt && !*szDiskPrompt))
01261         return ERROR_INVALID_PARAMETER;
01262 
01263     if ((dwContext & MSIINSTALLCONTEXT_MACHINE) && szUserSid)
01264         return ERROR_INVALID_PARAMETER;
01265 
01266     if (dwOptions & MSICODE_PATCH)
01267     {
01268         FIXME("Unhandled options MSICODE_PATCH\n");
01269         return ERROR_FUNCTION_FAILED;
01270     }
01271 
01272     rc = OpenSourceKey(szProduct, &sourcekey, MSICODE_PRODUCT, dwContext, FALSE);
01273     if (rc != ERROR_SUCCESS)
01274         return rc;
01275 
01276     OpenMediaSubkey(sourcekey, &mediakey, TRUE);
01277 
01278     sprintfW(szIndex, fmt, dwDiskId);
01279 
01280     size = 2;
01281     if (szVolumeLabel) size += lstrlenW(szVolumeLabel);
01282     if (szDiskPrompt) size += lstrlenW(szDiskPrompt);
01283 
01284     size *= sizeof(WCHAR);
01285     buffer = msi_alloc(size);
01286     *buffer = '\0';
01287 
01288     if (szVolumeLabel) lstrcpyW(buffer, szVolumeLabel);
01289     lstrcatW(buffer, szSemiColon);
01290     if (szDiskPrompt) lstrcatW(buffer, szDiskPrompt);
01291 
01292     RegSetValueExW(mediakey, szIndex, 0, REG_SZ, (LPBYTE)buffer, size);
01293     msi_free(buffer);
01294 
01295     RegCloseKey(sourcekey);
01296     RegCloseKey(mediakey);
01297 
01298     return ERROR_SUCCESS;
01299 }
01300 
01301 /******************************************************************
01302  *  MsiSourceListClearAllA (MSI.@)
01303  */
01304 UINT WINAPI MsiSourceListClearAllA( LPCSTR szProduct, LPCSTR szUserName, DWORD dwReserved )
01305 {
01306     FIXME("(%s %s %d)\n", debugstr_a(szProduct), debugstr_a(szUserName), dwReserved);
01307     return ERROR_SUCCESS;
01308 }
01309 
01310 /******************************************************************
01311  *  MsiSourceListClearAllW (MSI.@)
01312  */
01313 UINT WINAPI MsiSourceListClearAllW( LPCWSTR szProduct, LPCWSTR szUserName, DWORD dwReserved )
01314 {
01315     FIXME("(%s %s %d)\n", debugstr_w(szProduct), debugstr_w(szUserName), dwReserved);
01316     return ERROR_SUCCESS;
01317 }
01318 
01319 /******************************************************************
01320  *  MsiSourceListClearAllExA (MSI.@)
01321  */
01322 UINT WINAPI MsiSourceListClearAllExA( LPCSTR szProduct, LPCSTR szUserSid,
01323     MSIINSTALLCONTEXT dwContext, DWORD dwOptions )
01324 {
01325     FIXME("(%s %s %d %08x)\n", debugstr_a(szProduct), debugstr_a(szUserSid),
01326           dwContext, dwOptions);
01327     return ERROR_SUCCESS;
01328 }
01329 
01330 /******************************************************************
01331  *  MsiSourceListClearAllExW (MSI.@)
01332  */
01333 UINT WINAPI MsiSourceListClearAllExW( LPCWSTR szProduct, LPCWSTR szUserSid,
01334     MSIINSTALLCONTEXT dwContext, DWORD dwOptions )
01335 {
01336     FIXME("(%s %s %d %08x)\n", debugstr_w(szProduct), debugstr_w(szUserSid),
01337           dwContext, dwOptions);
01338     return ERROR_SUCCESS;
01339 }
01340 
01341 /******************************************************************
01342  *  MsiSourceListClearSourceA (MSI.@)
01343  */
01344 UINT WINAPI MsiSourceListClearSourceA(LPCSTR szProductCodeOrPatchCode, LPCSTR szUserSid,
01345                                       MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
01346                                       LPCSTR szSource)
01347 {
01348     FIXME("(%s %s %x %x %s)\n", debugstr_a(szProductCodeOrPatchCode), debugstr_a(szUserSid),
01349           dwContext, dwOptions, debugstr_a(szSource));
01350     return ERROR_SUCCESS;
01351 }
01352 
01353 /******************************************************************
01354  *  MsiSourceListClearSourceW (MSI.@)
01355  */
01356 UINT WINAPI MsiSourceListClearSourceW(LPCWSTR szProductCodeOrPatchCode, LPCWSTR szUserSid,
01357                                       MSIINSTALLCONTEXT dwContext, DWORD dwOptions,
01358                                       LPCWSTR szSource)
01359 {
01360     FIXME("(%s %s %x %x %s)\n", debugstr_w(szProductCodeOrPatchCode), debugstr_w(szUserSid),
01361           dwContext, dwOptions, debugstr_w(szSource));
01362     return ERROR_SUCCESS;
01363 }

Generated on Sat May 26 2012 04:22:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.