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

registry.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2005 Mike McCormack for CodeWeavers
00005  * Copyright 2005 Aric Stewart for CodeWeavers
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 
00024 #define COBJMACROS
00025 #define NONAMELESSUNION
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winreg.h"
00030 #include "winnls.h"
00031 #include "shlwapi.h"
00032 #include "wine/debug.h"
00033 #include "msi.h"
00034 #include "msipriv.h"
00035 #include "wincrypt.h"
00036 #include "wine/unicode.h"
00037 #include "winver.h"
00038 #include "winuser.h"
00039 #include "sddl.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00042 
00043 /* 
00044  * This module will be all the helper functions for registry access by the
00045  * installer bits. 
00046  */
00047 
00048 static const WCHAR szUserDataFeatures_fmt[] = {
00049     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00050     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00051     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00052     '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\','F','e','a','t','u','r','e','s',0};
00053 
00054 static const WCHAR szUserDataComp_fmt[] = {
00055     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00056     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00057     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00058     '%','s','\\','C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
00059 
00060 static const WCHAR szUserDataComponents_fmt[] = {
00061     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00062     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00063     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00064     '%','s','\\','C','o','m','p','o','n','e','n','t','s',0};
00065 
00066 static const WCHAR szUserDataProd_fmt[] = {
00067     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00068     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00069     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00070     '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
00071 
00072 static const WCHAR szUserDataProducts_fmt[] = {
00073     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00074     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00075     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00076     '%','s','\\','P','r','o','d','u','c','t','s',0};
00077 
00078 static const WCHAR szUserDataPatch_fmt[] = {
00079     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00080     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00081     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00082     '%','s','\\','P','a','t','c','h','e','s','\\','%','s',0};
00083 
00084 static const WCHAR szUserDataPatches_fmt[] = {
00085     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00086     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00087     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00088     '%','s','\\','P','a','t','c','h','e','s',0};
00089 
00090 static const WCHAR szUserDataProductPatches_fmt[] = {
00091     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00092     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00093     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00094     '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\','P','a','t','c','h','e','s',0};
00095 
00096 static const WCHAR szInstallProperties_fmt[] = {
00097     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00098     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00099     'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
00100     '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
00101     'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
00102 
00103 static const WCHAR szInstaller_LocalManaged_fmt[] = {
00104     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00105     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00106     'I','n','s','t','a','l','l','e','r','\\','M','a','n','a','g','e','d','\\','%','s','\\',
00107     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
00108 
00109 static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
00110     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00111     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00112     'I','n','s','t','a','l','l','e','r','\\','M','a','n','a','g','e','d','\\','%','s','\\',
00113     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
00114 
00115 static const WCHAR szInstaller_LocalManagedFeat_fmt[] = {
00116     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00117     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00118     'I','n','s','t','a','l','l','e','r','\\','M','a','n','a','g','e','d','\\','%','s','\\',
00119     'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s','\\','%','s',0};
00120 
00121 static const WCHAR szInstaller_Products[] = {
00122     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00123     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00124     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
00125 
00126 static const WCHAR szInstaller_Patches[] = {
00127     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00128     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00129     'I','n','s','t','a','l','l','e','r','\\','P','a','t','c','h','e','s',0};
00130 
00131 static const WCHAR szInstaller_Components[] = {
00132     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00133     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00134     'I','n','s','t','a','l','l','e','r','\\','C','o','m','p','o','n','e','n','t','s',0};
00135 
00136 static const WCHAR szInstaller_LocalClassesProducts[] = {
00137     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00138     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
00139 
00140 static const WCHAR szInstaller_LocalClassesFeatures[] = {
00141     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00142     'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s',0};
00143 
00144 static const WCHAR szInstaller_LocalClassesProd[] = {
00145     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00146     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s','\\',0};
00147 
00148 static const WCHAR szInstaller_LocalClassesFeat[] = {
00149     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00150     'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s','\\',0};
00151 
00152 static const WCHAR szInstaller_ClassesUpgradeCode[] = {
00153     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00154     'I','n','s','t','a','l','l','e','r','\\','U','p','g','r','a','d','e','C','o','d','e','s','\\',0};
00155 
00156 static const WCHAR szInstaller_ClassesUpgradeCodes[] = {
00157     'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
00158     'I','n','s','t','a','l','l','e','r','\\','U','p','g','r','a','d','e','C','o','d','e','s',0};
00159 
00160 static const WCHAR szInstaller_Features[] = {
00161     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00162     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00163     'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s','\\',0};
00164 
00165 static const WCHAR szInstaller_UpgradeCodes[] = {
00166     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00167     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00168     'I','n','s','t','a','l','l','e','r','\\','U','p','g','r','a','d','e','C','o','d','e','s','\\',0};
00169 
00170 static const WCHAR szInstaller_UserUpgradeCodes[] = {
00171     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00172     'I','n','s','t','a','l','l','e','r','\\','U','p','g','r','a','d','e','C','o','d','e','s','\\',0};
00173 
00174 static const WCHAR szUninstall[] = {
00175     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00176     'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00177     'U','n','i','n','s','t','a','l','l','\\',0};
00178 
00179 static const WCHAR szUninstall_32node[] = {
00180     'S','o','f','t','w','a','r','e','\\','W','o','w','6','4','3','2','N','o','d','e','\\',
00181     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
00182     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','U','n','i','n','s','t','a','l','l','\\',0};
00183 
00184 static const WCHAR szUserComponents[] = {
00185     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00186     'I','n','s','t','a','l','l','e','r','\\','C','o','m','p','o','n','e','n','t','s','\\',0};
00187 
00188 static const WCHAR szUserFeatures[] = {
00189     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00190     'I','n','s','t','a','l','l','e','r','\\','F','e','a','t','u','r','e','s','\\',0};
00191 
00192 static const WCHAR szUserProducts[] = {
00193     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00194     'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s','\\',0};
00195 
00196 static const WCHAR szUserPatches[] = {
00197     'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00198     'I','n','s','t','a','l','l','e','r','\\','P','a','t','c','h','e','s','\\',0};
00199 
00200 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
00201 {
00202     DWORD i,n=0;
00203 
00204     if (lstrlenW(in) != 32)
00205         return FALSE;
00206 
00207     out[n++]='{';
00208     for(i=0; i<8; i++)
00209         out[n++] = in[7-i];
00210     out[n++]='-';
00211     for(i=0; i<4; i++)
00212         out[n++] = in[11-i];
00213     out[n++]='-';
00214     for(i=0; i<4; i++)
00215         out[n++] = in[15-i];
00216     out[n++]='-';
00217     for(i=0; i<2; i++)
00218     {
00219         out[n++] = in[17+i*2];
00220         out[n++] = in[16+i*2];
00221     }
00222     out[n++]='-';
00223     for( ; i<8; i++)
00224     {
00225         out[n++] = in[17+i*2];
00226         out[n++] = in[16+i*2];
00227     }
00228     out[n++]='}';
00229     out[n]=0;
00230     return TRUE;
00231 }
00232 
00233 BOOL squash_guid(LPCWSTR in, LPWSTR out)
00234 {
00235     DWORD i,n=1;
00236     GUID guid;
00237 
00238     out[0] = 0;
00239 
00240     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
00241         return FALSE;
00242 
00243     for(i=0; i<8; i++)
00244         out[7-i] = in[n++];
00245     n++;
00246     for(i=0; i<4; i++)
00247         out[11-i] = in[n++];
00248     n++;
00249     for(i=0; i<4; i++)
00250         out[15-i] = in[n++];
00251     n++;
00252     for(i=0; i<2; i++)
00253     {
00254         out[17+i*2] = in[n++];
00255         out[16+i*2] = in[n++];
00256     }
00257     n++;
00258     for( ; i<8; i++)
00259     {
00260         out[17+i*2] = in[n++];
00261         out[16+i*2] = in[n++];
00262     }
00263     out[32]=0;
00264     return TRUE;
00265 }
00266 
00267 
00268 /* tables for encoding and decoding base85 */
00269 static const unsigned char table_dec85[0x80] = {
00270 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
00271 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
00272 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
00273 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
00274 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
00275 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
00276 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
00277 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
00278 };
00279 
00280 static const char table_enc85[] =
00281 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
00282 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
00283 "yz{}~";
00284 
00285 /*
00286  *  Converts a base85 encoded guid into a GUID pointer
00287  *  Base85 encoded GUIDs should be 20 characters long.
00288  *
00289  *  returns TRUE if successful, FALSE if not
00290  */
00291 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
00292 {
00293     DWORD i, val = 0, base = 1, *p;
00294 
00295     if (!str)
00296         return FALSE;
00297 
00298     p = (DWORD*) guid;
00299     for( i=0; i<20; i++ )
00300     {
00301         if( (i%5) == 0 )
00302         {
00303             val = 0;
00304             base = 1;
00305         }
00306         val += table_dec85[str[i]] * base;
00307         if( str[i] >= 0x80 )
00308             return FALSE;
00309         if( table_dec85[str[i]] == 0xff )
00310             return FALSE;
00311         if( (i%5) == 4 )
00312             p[i/5] = val;
00313         base *= 85;
00314     }
00315     return TRUE;
00316 }
00317 
00318 /*
00319  *  Encodes a base85 guid given a GUID pointer
00320  *  Caller should provide a 21 character buffer for the encoded string.
00321  *
00322  *  returns TRUE if successful, FALSE if not
00323  */
00324 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
00325 {
00326     unsigned int x, *p, i;
00327 
00328     p = (unsigned int*) guid;
00329     for( i=0; i<4; i++ )
00330     {
00331         x = p[i];
00332         *str++ = table_enc85[x%85];
00333         x = x/85;
00334         *str++ = table_enc85[x%85];
00335         x = x/85;
00336         *str++ = table_enc85[x%85];
00337         x = x/85;
00338         *str++ = table_enc85[x%85];
00339         x = x/85;
00340         *str++ = table_enc85[x%85];
00341     }
00342     *str = 0;
00343 
00344     return TRUE;
00345 }
00346 
00347 DWORD msi_version_str_to_dword(LPCWSTR p)
00348 {
00349     DWORD major, minor = 0, build = 0, version = 0;
00350 
00351     if (!p)
00352         return version;
00353 
00354     major = atoiW(p);
00355 
00356     p = strchrW(p, '.');
00357     if (p)
00358     {
00359         minor = atoiW(p+1);
00360         p = strchrW(p+1, '.');
00361         if (p)
00362             build = atoiW(p+1);
00363     }
00364 
00365     return MAKELONG(build, MAKEWORD(minor, major));
00366 }
00367 
00368 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
00369 {
00370     DWORD len;
00371     if (!value) value = szEmpty;
00372     len = (lstrlenW(value) + 1) * sizeof (WCHAR);
00373     return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
00374 }
00375 
00376 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
00377 {
00378     LPCWSTR p = value;
00379     while (*p) p += lstrlenW(p) + 1;
00380     return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
00381                            (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
00382 }
00383 
00384 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
00385 {
00386     return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
00387 }
00388 
00389 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
00390 {
00391     HKEY hsubkey = 0;
00392     LONG r;
00393 
00394     r = RegCreateKeyW( hkey, path, &hsubkey );
00395     if (r != ERROR_SUCCESS)
00396         return r;
00397     r = msi_reg_set_val_str( hsubkey, name, val );
00398     RegCloseKey( hsubkey );
00399     return r;
00400 }
00401 
00402 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
00403 {
00404     DWORD len = 0;
00405     LPWSTR val;
00406     LONG r;
00407 
00408     r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
00409     if (r != ERROR_SUCCESS)
00410         return NULL;
00411 
00412     len += sizeof (WCHAR);
00413     val = msi_alloc( len );
00414     if (!val)
00415         return NULL;
00416     val[0] = 0;
00417     RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
00418     return val;
00419 }
00420 
00421 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
00422 {
00423     DWORD type, len = sizeof (DWORD);
00424     LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
00425     return r == ERROR_SUCCESS && type == REG_DWORD;
00426 }
00427 
00428 static WCHAR *get_user_sid(void)
00429 {
00430     HANDLE token;
00431     DWORD size = 256;
00432     TOKEN_USER *user;
00433     WCHAR *ret;
00434 
00435     if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token )) return NULL;
00436     if (!(user = msi_alloc( size )))
00437     {
00438         CloseHandle( token );
00439         return NULL;
00440     }
00441     if (!GetTokenInformation( token, TokenUser, user, size, &size ))
00442     {
00443         msi_free( user );
00444         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !(user = msi_alloc( size )))
00445         {
00446             CloseHandle( token );
00447             return NULL;
00448         }
00449         GetTokenInformation( token, TokenUser, user, size, &size );
00450     }
00451     CloseHandle( token );
00452     if (!ConvertSidToStringSidW( user->User.Sid, &ret ))
00453     {
00454         msi_free( user );
00455         return NULL;
00456     }
00457     msi_free( user );
00458     return ret;
00459 }
00460 
00461 UINT MSIREG_OpenUninstallKey(const WCHAR *product, enum platform platform, HKEY *key, BOOL create)
00462 {
00463     WCHAR keypath[0x200];
00464 
00465     TRACE("%s\n", debugstr_w(product));
00466 
00467     if (is_64bit && platform == PLATFORM_INTEL)
00468     {
00469         strcpyW(keypath, szUninstall_32node);
00470         strcatW(keypath, product);
00471     }
00472     else
00473     {
00474         strcpyW(keypath, szUninstall);
00475         strcatW(keypath, product);
00476     }
00477     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, key, NULL);
00478     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, KEY_ALL_ACCESS, key);
00479 }
00480 
00481 UINT MSIREG_DeleteUninstallKey(const WCHAR *product, enum platform platform)
00482 {
00483     WCHAR keypath[0x200];
00484 
00485     TRACE("%s\n", debugstr_w(product));
00486 
00487     if (is_64bit && platform == PLATFORM_INTEL)
00488     {
00489         strcpyW(keypath, szUninstall_32node);
00490         strcatW(keypath, product);
00491     }
00492     else
00493     {
00494         strcpyW(keypath, szUninstall);
00495         strcatW(keypath, product);
00496     }
00497     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
00498 }
00499 
00500 UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
00501 {
00502     LPWSTR usersid = NULL;
00503     HKEY root = HKEY_LOCAL_MACHINE;
00504     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00505     WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH];
00506 
00507     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00508     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00509 
00510     if (context == MSIINSTALLCONTEXT_MACHINE)
00511     {
00512         strcpyW(keypath, szInstaller_LocalClassesProd);
00513         strcatW(keypath, squished_pc);
00514     }
00515     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
00516     {
00517         root = HKEY_CURRENT_USER;
00518         strcpyW(keypath, szUserProducts);
00519         strcatW(keypath, squished_pc);
00520     }
00521     else
00522     {
00523         if (!szUserSid)
00524         {
00525             if (!(usersid = get_user_sid()))
00526             {
00527                 ERR("Failed to retrieve user SID\n");
00528                 return ERROR_FUNCTION_FAILED;
00529             }
00530             szUserSid = usersid;
00531         }
00532         sprintfW(keypath, szInstaller_LocalManagedProd_fmt, szUserSid, squished_pc);
00533         LocalFree(usersid);
00534     }
00535     if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL);
00536     return RegOpenKeyExW(root, keypath, 0, access, key);
00537 }
00538 
00539 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
00540 {
00541     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00542 
00543     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00544     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00545 
00546     strcpyW(keypath, szUserProducts);
00547     strcatW(keypath, squished_pc);
00548     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
00549 }
00550 
00551 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
00552 {
00553     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00554 
00555     if (!squash_guid(szPatch, squished_pc)) return ERROR_FUNCTION_FAILED;
00556     TRACE("%s squished %s\n", debugstr_w(szPatch), debugstr_w(squished_pc));
00557 
00558     strcpyW(keypath, szUserPatches);
00559     strcatW(keypath, squished_pc);
00560 
00561     if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
00562     return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
00563 }
00564 
00565 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
00566 {
00567     LPWSTR usersid;
00568     HKEY root = HKEY_LOCAL_MACHINE;
00569     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00570     WCHAR squished_pc[GUID_SIZE], keypath[MAX_PATH];
00571 
00572     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00573     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00574 
00575     if (context == MSIINSTALLCONTEXT_MACHINE)
00576     {
00577         strcpyW(keypath, szInstaller_LocalClassesFeat);
00578         strcatW(keypath, squished_pc);
00579     }
00580     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
00581     {
00582         root = HKEY_CURRENT_USER;
00583         strcpyW(keypath, szUserFeatures);
00584         strcatW(keypath, squished_pc);
00585     }
00586     else
00587     {
00588         if (!(usersid = get_user_sid()))
00589         {
00590             ERR("Failed to retrieve user SID\n");
00591             return ERROR_FUNCTION_FAILED;
00592         }
00593         sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc);
00594         LocalFree(usersid);
00595     }
00596     if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL);
00597     return RegOpenKeyExW(root, keypath, 0, access, key);
00598 }
00599 
00600 UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
00601 {
00602     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00603 
00604     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00605     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00606 
00607     strcpyW(keypath, szUserFeatures);
00608     strcatW(keypath, squished_pc);
00609     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
00610 }
00611 
00612 static UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
00613 {
00614     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00615     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00616 
00617     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00618     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00619 
00620     strcpyW(keypath, szInstaller_Features);
00621     strcatW(keypath, squished_pc);
00622 
00623     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00624     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00625 }
00626 
00627 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
00628 {
00629     LPWSTR usersid;
00630     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00631     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00632 
00633     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00634     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00635 
00636     if (context == MSIINSTALLCONTEXT_MACHINE)
00637     {
00638         sprintfW(keypath, szUserDataFeatures_fmt, szLocalSid, squished_pc);
00639     }
00640     else
00641     {
00642         if (!(usersid = get_user_sid()))
00643         {
00644             ERR("Failed to retrieve user SID\n");
00645             return ERROR_FUNCTION_FAILED;
00646         }
00647         sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
00648         LocalFree(usersid);
00649     }
00650     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00651     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00652 }
00653 
00654 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY *key, BOOL create)
00655 {
00656     WCHAR squished_cc[GUID_SIZE], keypath[0x200];
00657 
00658     if (!squash_guid(szComponent, squished_cc)) return ERROR_FUNCTION_FAILED;
00659     TRACE("%s squished %s\n", debugstr_w(szComponent), debugstr_w(squished_cc));
00660 
00661     strcpyW(keypath, szUserComponents);
00662     strcatW(keypath, squished_cc);
00663 
00664     if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
00665     return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
00666 }
00667 
00668 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid, HKEY *key, BOOL create)
00669 {
00670     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00671     WCHAR comp[GUID_SIZE], keypath[0x200];
00672     LPWSTR usersid;
00673 
00674     if (!squash_guid(szComponent, comp)) return ERROR_FUNCTION_FAILED;
00675     TRACE("%s squished %s\n", debugstr_w(szComponent), debugstr_w(comp));
00676 
00677     if (!szUserSid)
00678     {
00679         if (!(usersid = get_user_sid()))
00680         {
00681             ERR("Failed to retrieve user SID\n");
00682             return ERROR_FUNCTION_FAILED;
00683         }
00684         sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
00685         LocalFree(usersid);
00686     }
00687     else
00688         sprintfW(keypath, szUserDataComp_fmt, szUserSid, comp);
00689 
00690     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00691     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00692 }
00693 
00694 UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid)
00695 {
00696     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00697     WCHAR comp[GUID_SIZE], keypath[0x200];
00698     LPWSTR usersid;
00699     HKEY hkey;
00700     LONG r;
00701 
00702     if (!squash_guid(szComponent, comp)) return ERROR_FUNCTION_FAILED;
00703     TRACE("%s squished %s\n", debugstr_w(szComponent), debugstr_w(comp));
00704 
00705     if (!szUserSid)
00706     {
00707         if (!(usersid = get_user_sid()))
00708         {
00709             ERR("Failed to retrieve user SID\n");
00710             return ERROR_FUNCTION_FAILED;
00711         }
00712         sprintfW(keypath, szUserDataComponents_fmt, usersid);
00713         LocalFree(usersid);
00714     }
00715     else
00716         sprintfW(keypath, szUserDataComponents_fmt, szUserSid);
00717 
00718     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
00719     r = RegDeleteTreeW(hkey, comp);
00720     RegCloseKey(hkey);
00721     return r;
00722 }
00723 
00724 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext, LPCWSTR szUserSid, HKEY *key, BOOL create)
00725 {
00726     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00727     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00728     LPWSTR usersid;
00729 
00730     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00731     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00732 
00733     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
00734         sprintfW(keypath, szUserDataProd_fmt, szLocalSid, squished_pc);
00735     else if (szUserSid)
00736         sprintfW(keypath, szUserDataProd_fmt, szUserSid, squished_pc);
00737     else
00738     {
00739         if (!(usersid = get_user_sid()))
00740         {
00741             ERR("Failed to retrieve user SID\n");
00742             return ERROR_FUNCTION_FAILED;
00743         }
00744         sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
00745         LocalFree(usersid);
00746     }
00747     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00748     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00749 }
00750 
00751 UINT MSIREG_OpenUserDataPatchKey(LPCWSTR szPatch, MSIINSTALLCONTEXT dwContext, HKEY *key, BOOL create)
00752 {
00753     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00754     WCHAR squished_patch[GUID_SIZE], keypath[0x200];
00755     LPWSTR usersid;
00756 
00757     if (!squash_guid(szPatch, squished_patch)) return ERROR_FUNCTION_FAILED;
00758     TRACE("%s squished %s\n", debugstr_w(szPatch), debugstr_w(squished_patch));
00759 
00760     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
00761         sprintfW(keypath, szUserDataPatch_fmt, szLocalSid, squished_patch);
00762     else
00763     {
00764         if (!(usersid = get_user_sid()))
00765         {
00766             ERR("Failed to retrieve user SID\n");
00767             return ERROR_FUNCTION_FAILED;
00768         }
00769         sprintfW(keypath, szUserDataPatch_fmt, usersid, squished_patch);
00770         LocalFree(usersid);
00771     }
00772     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00773     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00774 }
00775 
00776 UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context)
00777 {
00778     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00779     WCHAR squished_patch[GUID_SIZE], keypath[0x200];
00780     LPWSTR usersid;
00781     HKEY hkey;
00782     LONG r;
00783 
00784     if (!squash_guid(patch, squished_patch)) return ERROR_FUNCTION_FAILED;
00785     TRACE("%s squished %s\n", debugstr_w(patch), debugstr_w(squished_patch));
00786 
00787     if (context == MSIINSTALLCONTEXT_MACHINE)
00788         sprintfW(keypath, szUserDataPatches_fmt, szLocalSid);
00789     else
00790     {
00791         if (!(usersid = get_user_sid()))
00792         {
00793             ERR("Failed to retrieve user SID\n");
00794             return ERROR_FUNCTION_FAILED;
00795         }
00796         sprintfW(keypath, szUserDataPatches_fmt, usersid);
00797         LocalFree(usersid);
00798     }
00799     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
00800     r = RegDeleteTreeW(hkey, squished_patch);
00801     RegCloseKey(hkey);
00802     return r;
00803 }
00804 
00805 UINT MSIREG_OpenUserDataProductPatchesKey(LPCWSTR product, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
00806 {
00807     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00808     WCHAR squished_product[GUID_SIZE], keypath[0x200];
00809     LPWSTR usersid;
00810 
00811     if (!squash_guid(product, squished_product)) return ERROR_FUNCTION_FAILED;
00812     TRACE("%s squished %s\n", debugstr_w(product), debugstr_w(squished_product));
00813 
00814     if (context == MSIINSTALLCONTEXT_MACHINE)
00815         sprintfW(keypath, szUserDataProductPatches_fmt, szLocalSid, squished_product);
00816     else
00817     {
00818         if (!(usersid = get_user_sid()))
00819         {
00820             ERR("Failed to retrieve user SID\n");
00821             return ERROR_FUNCTION_FAILED;
00822         }
00823         sprintfW(keypath, szUserDataProductPatches_fmt, usersid, squished_product);
00824         LocalFree(usersid);
00825     }
00826     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00827     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00828 }
00829 
00830 UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext, LPCWSTR szUserSid, HKEY *key, BOOL create)
00831 {
00832     LPWSTR usersid;
00833     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00834     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00835 
00836     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00837     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00838 
00839     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
00840         sprintfW(keypath, szInstallProperties_fmt, szLocalSid, squished_pc);
00841     else if (szUserSid)
00842         sprintfW(keypath, szInstallProperties_fmt, szUserSid, squished_pc);
00843     else
00844     {
00845         if (!(usersid = get_user_sid()))
00846         {
00847             ERR("Failed to retrieve user SID\n");
00848             return ERROR_FUNCTION_FAILED;
00849         }
00850         sprintfW(keypath, szInstallProperties_fmt, usersid, squished_pc);
00851         LocalFree(usersid);
00852     }
00853     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00854     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00855 }
00856 
00857 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
00858 {
00859     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00860     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00861     LPWSTR usersid;
00862     HKEY hkey;
00863     LONG r;
00864 
00865     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00866     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00867 
00868     if (!(usersid = get_user_sid()))
00869     {
00870         ERR("Failed to retrieve user SID\n");
00871         return ERROR_FUNCTION_FAILED;
00872     }
00873     sprintfW(keypath, szUserDataProducts_fmt, usersid);
00874     LocalFree(usersid);
00875 
00876     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
00877     r = RegDeleteTreeW(hkey, squished_pc);
00878     RegCloseKey(hkey);
00879     return r;
00880 }
00881 
00882 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
00883 {
00884     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00885     WCHAR squished_pc[GUID_SIZE];
00886     HKEY hkey;
00887     LONG r;
00888 
00889     if (!squash_guid(szProduct, squished_pc)) return ERROR_FUNCTION_FAILED;
00890     TRACE("%s squished %s\n", debugstr_w(szProduct), debugstr_w(squished_pc));
00891 
00892     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_Products, 0, access, &hkey)) return ERROR_SUCCESS;
00893     r = RegDeleteTreeW(hkey, squished_pc);
00894     RegCloseKey(hkey);
00895     return r;
00896 }
00897 
00898 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
00899 {
00900     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00901     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00902 
00903     if (!squash_guid(szPatch, squished_pc)) return ERROR_FUNCTION_FAILED;
00904     TRACE("%s squished %s\n", debugstr_w(szPatch), debugstr_w(squished_pc));
00905 
00906     sprintfW(keypath, szInstaller_Patches, squished_pc);
00907 
00908     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00909     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00910 }
00911 
00912 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY *key, BOOL create)
00913 {
00914     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00915     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00916 
00917     if (!squash_guid(szUpgradeCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00918     TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
00919 
00920     strcpyW(keypath, szInstaller_UpgradeCodes);
00921     strcatW(keypath, squished_pc);
00922 
00923     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00924     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00925 }
00926 
00927 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
00928 {
00929     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00930 
00931     if (!squash_guid(szUpgradeCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00932     TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
00933 
00934     strcpyW(keypath, szInstaller_UserUpgradeCodes);
00935     strcatW(keypath, squished_pc);
00936 
00937     if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
00938     return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
00939 }
00940 
00941 UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
00942 {
00943     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00944 
00945     if (!squash_guid(szUpgradeCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00946     TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
00947 
00948     strcpyW(keypath, szInstaller_UserUpgradeCodes);
00949     strcatW(keypath, squished_pc);
00950     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
00951 }
00952 
00953 UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
00954 {
00955     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00956     WCHAR squished_pc[GUID_SIZE];
00957     HKEY hkey;
00958     LONG r;
00959 
00960     if (!squash_guid(szProductCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00961     TRACE("%s squished %s\n", debugstr_w(szProductCode), debugstr_w(squished_pc));
00962 
00963     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProducts, 0, access, &hkey)) return ERROR_SUCCESS;
00964     r = RegDeleteTreeW(hkey, squished_pc);
00965     RegCloseKey(hkey);
00966     return r;
00967 }
00968 
00969 UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
00970 {
00971     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00972     WCHAR squished_pc[GUID_SIZE];
00973     HKEY hkey;
00974     LONG r;
00975 
00976     if (!squash_guid(szProductCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00977     TRACE("%s squished %s\n", debugstr_w(szProductCode), debugstr_w(squished_pc));
00978 
00979     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesFeatures, 0, access, &hkey)) return ERROR_SUCCESS;
00980     r = RegDeleteTreeW(hkey, squished_pc);
00981     RegCloseKey(hkey);
00982     return r;
00983 }
00984 
00985 UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY *key, BOOL create)
00986 {
00987     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
00988     WCHAR squished_pc[GUID_SIZE], keypath[0x200];
00989 
00990     if (!squash_guid(szUpgradeCode, squished_pc)) return ERROR_FUNCTION_FAILED;
00991     TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
00992 
00993     strcpyW(keypath, szInstaller_ClassesUpgradeCode);
00994     strcatW(keypath, squished_pc);
00995 
00996     if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
00997     return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
00998 }
00999 
01000 UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)
01001 {
01002     REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
01003     WCHAR squished_pc[GUID_SIZE];
01004     HKEY hkey;
01005     LONG r;
01006 
01007     if (!squash_guid(szUpgradeCode, squished_pc)) return ERROR_FUNCTION_FAILED;
01008     TRACE("%s squished %s\n", debugstr_w(szUpgradeCode), debugstr_w(squished_pc));
01009 
01010     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szInstaller_ClassesUpgradeCodes, 0, access, &hkey)) return ERROR_SUCCESS;
01011     r = RegDeleteTreeW(hkey, squished_pc);
01012     RegCloseKey(hkey);
01013     return r;
01014 }
01015 
01016 /*************************************************************************
01017  *  MsiDecomposeDescriptorW   [MSI.@]
01018  *
01019  * Decomposes an MSI descriptor into product, feature and component parts.
01020  * An MSI descriptor is a string of the form:
01021  *   [base 85 guid] [feature code] '>' [base 85 guid]
01022  *
01023  * PARAMS
01024  *   szDescriptor  [I]  the descriptor to decompose
01025  *   szProduct     [O]  buffer of MAX_FEATURE_CHARS+1 for the product guid
01026  *   szFeature     [O]  buffer of MAX_FEATURE_CHARS+1 for the feature code
01027  *   szComponent   [O]  buffer of MAX_FEATURE_CHARS+1 for the component guid
01028  *   pUsed         [O]  the length of the descriptor
01029  *
01030  * RETURNS
01031  *   ERROR_SUCCESS             if everything worked correctly
01032  *   ERROR_INVALID_PARAMETER   if the descriptor was invalid
01033  *
01034  */
01035 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
01036                 LPWSTR szFeature, LPWSTR szComponent, LPDWORD pUsed )
01037 {
01038     UINT r, len;
01039     LPWSTR p;
01040     GUID product, component;
01041 
01042     TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
01043           szFeature, szComponent, pUsed);
01044 
01045     r = decode_base85_guid( szDescriptor, &product );
01046     if( !r )
01047         return ERROR_INVALID_PARAMETER;
01048 
01049     TRACE("product %s\n", debugstr_guid( &product ));
01050 
01051     p = strchrW(&szDescriptor[20],'>');
01052     if( !p )
01053         return ERROR_INVALID_PARAMETER;
01054 
01055     len = (p - &szDescriptor[20]);
01056     if( len > MAX_FEATURE_CHARS )
01057         return ERROR_INVALID_PARAMETER;
01058 
01059     TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
01060 
01061     r = decode_base85_guid( p+1, &component );
01062     if( !r )
01063         return ERROR_INVALID_PARAMETER;
01064 
01065     TRACE("component %s\n", debugstr_guid( &component ));
01066 
01067     if (szProduct)
01068         StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
01069     if (szComponent)
01070         StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
01071     if (szFeature)
01072     {
01073         memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
01074         szFeature[len] = 0;
01075     }
01076     len = ( &p[21] - szDescriptor );
01077 
01078     TRACE("length = %d\n", len);
01079     if (pUsed) *pUsed = len;
01080 
01081     return ERROR_SUCCESS;
01082 }
01083 
01084 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
01085                 LPSTR szFeature, LPSTR szComponent, LPDWORD pUsed )
01086 {
01087     WCHAR product[MAX_FEATURE_CHARS+1];
01088     WCHAR feature[MAX_FEATURE_CHARS+1];
01089     WCHAR component[MAX_FEATURE_CHARS+1];
01090     LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
01091     UINT r;
01092 
01093     TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
01094           szFeature, szComponent, pUsed);
01095 
01096     str = strdupAtoW( szDescriptor );
01097     if( szDescriptor && !str )
01098         return ERROR_OUTOFMEMORY;
01099 
01100     if (szProduct)
01101         p = product;
01102     if (szFeature)
01103         f = feature;
01104     if (szComponent)
01105         c = component;
01106 
01107     r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
01108 
01109     if (r == ERROR_SUCCESS)
01110     {
01111         WideCharToMultiByte( CP_ACP, 0, p, -1,
01112                              szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
01113         WideCharToMultiByte( CP_ACP, 0, f, -1,
01114                              szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
01115         WideCharToMultiByte( CP_ACP, 0, c, -1,
01116                              szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
01117     }
01118 
01119     msi_free( str );
01120 
01121     return r;
01122 }
01123 
01124 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
01125 {
01126     DWORD r;
01127     WCHAR szwGuid[GUID_SIZE];
01128 
01129     TRACE("%d %p\n", index, lpguid);
01130 
01131     if (NULL == lpguid)
01132         return ERROR_INVALID_PARAMETER;
01133     r = MsiEnumProductsW(index, szwGuid);
01134     if( r == ERROR_SUCCESS )
01135         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
01136 
01137     return r;
01138 }
01139 
01140 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
01141 {
01142     TRACE("%d %p\n", index, lpguid);
01143 
01144     if (NULL == lpguid)
01145         return ERROR_INVALID_PARAMETER;
01146 
01147     return MsiEnumProductsExW( NULL, szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid,
01148                                NULL, NULL, NULL );
01149 }
01150 
01151 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
01152       LPSTR szFeature, LPSTR szParent)
01153 {
01154     DWORD r;
01155     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
01156     LPWSTR szwProduct = NULL;
01157 
01158     TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
01159 
01160     if( szProduct )
01161     {
01162         szwProduct = strdupAtoW( szProduct );
01163         if( !szwProduct )
01164             return ERROR_OUTOFMEMORY;
01165     }
01166 
01167     r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
01168     if( r == ERROR_SUCCESS )
01169     {
01170         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
01171                             szFeature, GUID_SIZE, NULL, NULL);
01172         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
01173                             szParent, GUID_SIZE, NULL, NULL);
01174     }
01175 
01176     msi_free( szwProduct);
01177 
01178     return r;
01179 }
01180 
01181 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
01182       LPWSTR szFeature, LPWSTR szParent)
01183 {
01184     HKEY hkeyProduct = 0;
01185     DWORD r, sz;
01186 
01187     TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
01188 
01189     if( !szProduct )
01190         return ERROR_INVALID_PARAMETER;
01191 
01192     r = MSIREG_OpenInstallerFeaturesKey(szProduct,&hkeyProduct,FALSE);
01193     if( r != ERROR_SUCCESS )
01194         return ERROR_NO_MORE_ITEMS;
01195 
01196     sz = GUID_SIZE;
01197     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
01198     RegCloseKey(hkeyProduct);
01199 
01200     return r;
01201 }
01202 
01203 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
01204 {
01205     DWORD r;
01206     WCHAR szwGuid[GUID_SIZE];
01207 
01208     TRACE("%u, %p\n", index, lpguid);
01209 
01210     if (!lpguid) return ERROR_INVALID_PARAMETER;
01211 
01212     r = MsiEnumComponentsW(index, szwGuid);
01213     if( r == ERROR_SUCCESS )
01214         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
01215 
01216     return r;
01217 }
01218 
01219 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
01220 {
01221     TRACE("%u, %p\n", index, lpguid);
01222 
01223     if (!lpguid) return ERROR_INVALID_PARAMETER;
01224 
01225     return MsiEnumComponentsExW( szAllSid, MSIINSTALLCONTEXT_ALL, index, lpguid, NULL, NULL, NULL );
01226 }
01227 
01228 UINT WINAPI MsiEnumComponentsExA( LPCSTR user_sid, DWORD ctx, DWORD index, CHAR guid[39],
01229                                   MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
01230 {
01231     UINT r;
01232     WCHAR *user_sidW = NULL, *sidW = NULL, guidW[GUID_SIZE];
01233 
01234     TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_a(user_sid), ctx, index, guid, installed_ctx,
01235           sid, sid_len);
01236 
01237     if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
01238     if (user_sid && !(user_sidW = strdupAtoW( user_sid ))) return ERROR_OUTOFMEMORY;
01239     if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
01240     {
01241         msi_free( user_sidW );
01242         return ERROR_OUTOFMEMORY;
01243     }
01244     r = MsiEnumComponentsExW( user_sidW, ctx, index, guidW, installed_ctx, sidW, sid_len );
01245     if (r == ERROR_SUCCESS)
01246     {
01247         if (guid) WideCharToMultiByte( CP_ACP, 0, guidW, GUID_SIZE, guid, GUID_SIZE, NULL, NULL );
01248         if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
01249     }
01250     msi_free( user_sidW );
01251     msi_free( sidW );
01252     return r;
01253 }
01254 
01255 static UINT fetch_machine_component( DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
01256                                      MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
01257 {
01258     static const WCHAR componentsW[] =
01259         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
01260          'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
01261          'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a','\\',
01262          'S','-','1','-','5','-','1','8','\\','C','o','m','p','o','n','e','n','t','s',0};
01263     UINT r = ERROR_SUCCESS;
01264     WCHAR component[GUID_SIZE];
01265     DWORD i = 0, len_component;
01266     REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
01267     HKEY key_components;
01268 
01269     if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, componentsW, 0, access, &key_components ))
01270         return ERROR_NO_MORE_ITEMS;
01271 
01272     len_component = sizeof(component)/sizeof(component[0]);
01273     while (!RegEnumKeyExW( key_components, i, component, &len_component, NULL, NULL, NULL, NULL ))
01274     {
01275         if (*idx == index) goto found;
01276         (*idx)++;
01277         len_component = sizeof(component)/sizeof(component[0]);
01278         i++;
01279     }
01280     RegCloseKey( key_components );
01281     return ERROR_NO_MORE_ITEMS;
01282 
01283 found:
01284     if (sid_len)
01285     {
01286         if (*sid_len < 1)
01287         {
01288             *sid_len = 1;
01289             r = ERROR_MORE_DATA;
01290         }
01291         else if (sid)
01292         {
01293             *sid_len = 0;
01294             sid[0] = 0;
01295         }
01296     }
01297     if (guid) unsquash_guid( component, guid );
01298     if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
01299     RegCloseKey( key_components );
01300     return r;
01301 }
01302 
01303 static UINT fetch_user_component( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx,
01304                                   WCHAR guid[39], MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid,
01305                                   LPDWORD sid_len )
01306 {
01307     static const WCHAR userdataW[] =
01308         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
01309          'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
01310          'I','n','s','t','a','l','l','e','r','\\','U','s','e','r','D','a','t','a',0};
01311     static const WCHAR componentsW[] = {'\\','C','o','m','p','o','n','e','n','t','s',0};
01312     UINT r = ERROR_SUCCESS;
01313     WCHAR path[MAX_PATH], component[GUID_SIZE], user[128];
01314     DWORD i = 0, j = 0, len_component, len_user;
01315     REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
01316     HKEY key_users, key_components;
01317 
01318     if (ctx == MSIINSTALLCONTEXT_USERMANAGED) /* FIXME: were to find these? */
01319         return ERROR_NO_MORE_ITEMS;
01320 
01321     if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, userdataW, 0, access, &key_users ))
01322         return ERROR_NO_MORE_ITEMS;
01323 
01324     len_user = sizeof(user)/sizeof(user[0]);
01325     while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
01326     {
01327         if ((strcmpW( usersid, szAllSid ) && strcmpW( usersid, user )) ||
01328             !strcmpW( szLocalSid, user ))
01329         {
01330             i++;
01331             len_user = sizeof(user)/sizeof(user[0]);
01332             continue;
01333         }
01334         strcpyW( path, user );
01335         strcatW( path, componentsW );
01336         if (RegOpenKeyExW( key_users, path, 0, access, &key_components ))
01337         {
01338             i++;
01339             len_user = sizeof(user)/sizeof(user[0]);
01340             continue;
01341         }
01342         len_component = sizeof(component)/sizeof(component[0]);
01343         while (!RegEnumKeyExW( key_components, j, component, &len_component, NULL, NULL, NULL, NULL ))
01344         {
01345             if (*idx == index) goto found;
01346             (*idx)++;
01347             len_component = sizeof(component)/sizeof(component[0]);
01348             j++;
01349         }
01350         RegCloseKey( key_components );
01351         len_user = sizeof(user)/sizeof(user[0]);
01352         i++;
01353     }
01354     RegCloseKey( key_users );
01355     return ERROR_NO_MORE_ITEMS;
01356 
01357 found:
01358     if (sid_len)
01359     {
01360         if (*sid_len < len_user + 1)
01361         {
01362             *sid_len = len_user + 1;
01363             r = ERROR_MORE_DATA;
01364         }
01365         else if (sid)
01366         {
01367             *sid_len = len_user;
01368             strcpyW( sid, user );
01369         }
01370     }
01371     if (guid) unsquash_guid( component, guid );
01372     if (installed_ctx) *installed_ctx = ctx;
01373     RegCloseKey( key_components );
01374     RegCloseKey( key_users );
01375     return r;
01376 }
01377 
01378 static UINT enum_components( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
01379                              MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
01380 {
01381     UINT r = ERROR_NO_MORE_ITEMS;
01382     WCHAR *user = NULL;
01383 
01384     if (!usersid)
01385     {
01386         usersid = user = get_user_sid();
01387         if (!user) return ERROR_FUNCTION_FAILED;
01388     }
01389     if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
01390     {
01391         r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERMANAGED, index, idx, guid,
01392                                   installed_ctx, sid, sid_len );
01393         if (r != ERROR_NO_MORE_ITEMS) goto done;
01394     }
01395     if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
01396     {
01397         r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index, idx, guid,
01398                                   installed_ctx, sid, sid_len );
01399         if (r != ERROR_NO_MORE_ITEMS) goto done;
01400     }
01401     if (ctx & MSIINSTALLCONTEXT_MACHINE)
01402     {
01403         r = fetch_machine_component( MSIINSTALLCONTEXT_MACHINE, index, idx, guid, installed_ctx,
01404                                      sid, sid_len );
01405         if (r != ERROR_NO_MORE_ITEMS) goto done;
01406     }
01407 
01408 done:
01409     LocalFree( user );
01410     return r;
01411 }
01412 
01413 UINT WINAPI MsiEnumComponentsExW( LPCWSTR user_sid, DWORD ctx, DWORD index, WCHAR guid[39],
01414                                   MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
01415 {
01416     UINT r;
01417     DWORD idx = 0;
01418     static DWORD last_index;
01419 
01420     TRACE("%s, %u, %u, %p, %p, %p, %p\n", debugstr_w(user_sid), ctx, index, guid, installed_ctx,
01421           sid, sid_len);
01422 
01423     if ((sid && !sid_len) || !ctx || (user_sid && ctx == MSIINSTALLCONTEXT_MACHINE))
01424         return ERROR_INVALID_PARAMETER;
01425 
01426     if (index && index - last_index != 1)
01427         return ERROR_INVALID_PARAMETER;
01428 
01429     if (!index) last_index = 0;
01430 
01431     r = enum_components( user_sid, ctx, index, &idx, guid, installed_ctx, sid, sid_len );
01432     if (r == ERROR_SUCCESS)
01433         last_index = index;
01434     else
01435         last_index = 0;
01436 
01437     return r;
01438 }
01439 
01440 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
01441 {
01442     DWORD r;
01443     WCHAR szwProduct[GUID_SIZE];
01444     LPWSTR szwComponent = NULL;
01445 
01446     TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
01447 
01448     if ( !szProduct )
01449         return ERROR_INVALID_PARAMETER;
01450 
01451     if( szComponent )
01452     {
01453         szwComponent = strdupAtoW( szComponent );
01454         if( !szwComponent )
01455             return ERROR_OUTOFMEMORY;
01456     }
01457 
01458     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
01459     if( r == ERROR_SUCCESS )
01460     {
01461         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
01462                             szProduct, GUID_SIZE, NULL, NULL);
01463     }
01464 
01465     msi_free( szwComponent);
01466 
01467     return r;
01468 }
01469 
01470 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
01471 {
01472     HKEY hkeyComp = 0;
01473     DWORD r, sz;
01474     WCHAR szValName[SQUISH_GUID_SIZE];
01475 
01476     TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
01477 
01478     if (!szComponent || !*szComponent || !szProduct)
01479         return ERROR_INVALID_PARAMETER;
01480 
01481     if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkeyComp, FALSE) != ERROR_SUCCESS &&
01482         MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkeyComp, FALSE) != ERROR_SUCCESS)
01483         return ERROR_UNKNOWN_COMPONENT;
01484 
01485     /* see if there are any products at all */
01486     sz = SQUISH_GUID_SIZE;
01487     r = RegEnumValueW(hkeyComp, 0, szValName, &sz, NULL, NULL, NULL, NULL);
01488     if (r != ERROR_SUCCESS)
01489     {
01490         RegCloseKey(hkeyComp);
01491 
01492         if (index != 0)
01493             return ERROR_INVALID_PARAMETER;
01494 
01495         return ERROR_UNKNOWN_COMPONENT;
01496     }
01497 
01498     sz = SQUISH_GUID_SIZE;
01499     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
01500     if( r == ERROR_SUCCESS )
01501     {
01502         unsquash_guid(szValName, szProduct);
01503         TRACE("-> %s\n", debugstr_w(szProduct));
01504     }
01505     RegCloseKey(hkeyComp);
01506     return r;
01507 }
01508 
01509 static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
01510                 awstring *lpQualBuf, LPDWORD pcchQual,
01511                 awstring *lpAppBuf, LPDWORD pcchAppBuf )
01512 {
01513     DWORD name_sz, val_sz, name_max, val_max, type, ofs;
01514     LPWSTR name = NULL, val = NULL;
01515     UINT r, r2;
01516     HKEY key;
01517 
01518     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
01519           lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
01520 
01521     if (!szComponent)
01522         return ERROR_INVALID_PARAMETER;
01523 
01524     r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
01525     if (r != ERROR_SUCCESS)
01526         return ERROR_UNKNOWN_COMPONENT;
01527 
01528     /* figure out how big the name is we want to return */
01529     name_max = 0x10;
01530     r = ERROR_OUTOFMEMORY;
01531     name = msi_alloc( name_max * sizeof(WCHAR) );
01532     if (!name)
01533         goto end;
01534 
01535     val_max = 0x10;
01536     r = ERROR_OUTOFMEMORY;
01537     val = msi_alloc( val_max );
01538     if (!val)
01539         goto end;
01540 
01541     /* loop until we allocate enough memory */
01542     while (1)
01543     {
01544         name_sz = name_max;
01545         val_sz = val_max;
01546         r = RegEnumValueW( key, iIndex, name, &name_sz,
01547                            NULL, &type, (LPBYTE)val, &val_sz );
01548         if (r == ERROR_SUCCESS)
01549             break;
01550         if (r != ERROR_MORE_DATA)
01551             goto end;
01552  
01553         if (type != REG_MULTI_SZ)
01554         {
01555             ERR("component data has wrong type (%d)\n", type);
01556             goto end;
01557         }
01558 
01559         r = ERROR_OUTOFMEMORY;
01560         if ((name_sz+1) >= name_max)
01561         {
01562             name_max *= 2;
01563             msi_free( name );
01564             name = msi_alloc( name_max * sizeof (WCHAR) );
01565             if (!name)
01566                 goto end;
01567             continue;
01568         }
01569         if (val_sz > val_max)
01570         {
01571             val_max = val_sz + sizeof (WCHAR);
01572             msi_free( val );
01573             val = msi_alloc( val_max * sizeof (WCHAR) );
01574             if (!val)
01575                 goto end;
01576             continue;
01577         }
01578         ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
01579         goto end;
01580     }
01581 
01582     ofs = 0;
01583     r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
01584     if (r != ERROR_SUCCESS)
01585         goto end;
01586 
01587     TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
01588 
01589     r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
01590     r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
01591 
01592     if (r2 != ERROR_SUCCESS)
01593         r = r2;
01594 
01595 end:
01596     msi_free(val);
01597     msi_free(name);
01598     RegCloseKey(key);
01599 
01600     return r;
01601 }
01602 
01603 /*************************************************************************
01604  *  MsiEnumComponentQualifiersA [MSI.@]
01605  */
01606 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
01607                 LPSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
01608                 LPSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
01609 {
01610     awstring qual, appdata;
01611     LPWSTR comp;
01612     UINT r;
01613 
01614     TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
01615           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
01616           pcchApplicationDataBuf);
01617 
01618     comp = strdupAtoW( szComponent );
01619     if (szComponent && !comp)
01620         return ERROR_OUTOFMEMORY;
01621 
01622     qual.unicode = FALSE;
01623     qual.str.a = lpQualifierBuf;
01624 
01625     appdata.unicode = FALSE;
01626     appdata.str.a = lpApplicationDataBuf;
01627 
01628     r = MSI_EnumComponentQualifiers( comp, iIndex,
01629               &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
01630     msi_free( comp );
01631     return r;
01632 }
01633 
01634 /*************************************************************************
01635  *  MsiEnumComponentQualifiersW [MSI.@]
01636  */
01637 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
01638                 LPWSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
01639                 LPWSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
01640 {
01641     awstring qual, appdata;
01642 
01643     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
01644           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
01645           pcchApplicationDataBuf);
01646 
01647     qual.unicode = TRUE;
01648     qual.str.w = lpQualifierBuf;
01649 
01650     appdata.unicode = TRUE;
01651     appdata.str.w = lpApplicationDataBuf;
01652 
01653     return MSI_EnumComponentQualifiers( szComponent, iIndex,
01654                  &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
01655 }
01656 
01657 /*************************************************************************
01658  *  MsiEnumRelatedProductsW   [MSI.@]
01659  *
01660  */
01661 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
01662                                     DWORD iProductIndex, LPWSTR lpProductBuf)
01663 {
01664     UINT r;
01665     HKEY hkey;
01666     DWORD dwSize = SQUISH_GUID_SIZE;
01667     WCHAR szKeyName[SQUISH_GUID_SIZE];
01668 
01669     TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
01670           iProductIndex, lpProductBuf);
01671 
01672     if (NULL == szUpgradeCode)
01673         return ERROR_INVALID_PARAMETER;
01674     if (NULL == lpProductBuf)
01675         return ERROR_INVALID_PARAMETER;
01676 
01677     r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
01678     if (r != ERROR_SUCCESS)
01679         return ERROR_NO_MORE_ITEMS;
01680 
01681     r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
01682     if( r == ERROR_SUCCESS )
01683         unsquash_guid(szKeyName, lpProductBuf);
01684     RegCloseKey(hkey);
01685 
01686     return r;
01687 }
01688 
01689 /*************************************************************************
01690  *  MsiEnumRelatedProductsA   [MSI.@]
01691  *
01692  */
01693 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
01694                                     DWORD iProductIndex, LPSTR lpProductBuf)
01695 {
01696     LPWSTR szwUpgradeCode = NULL;
01697     WCHAR productW[GUID_SIZE];
01698     UINT r;
01699 
01700     TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
01701           iProductIndex, lpProductBuf);
01702 
01703     if (szUpgradeCode)
01704     {
01705         szwUpgradeCode = strdupAtoW( szUpgradeCode );
01706         if( !szwUpgradeCode )
01707             return ERROR_OUTOFMEMORY;
01708     }
01709 
01710     r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
01711                                  iProductIndex, productW );
01712     if (r == ERROR_SUCCESS)
01713     {
01714         WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
01715                              lpProductBuf, GUID_SIZE, NULL, NULL );
01716     }
01717     msi_free( szwUpgradeCode);
01718     return r;
01719 }
01720 
01721 /***********************************************************************
01722  * MsiEnumPatchesExA            [MSI.@]
01723  */
01724 UINT WINAPI MsiEnumPatchesExA(LPCSTR szProductCode, LPCSTR szUserSid,
01725         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPSTR szPatchCode,
01726         LPSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
01727         LPSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
01728 {
01729     LPWSTR prodcode = NULL;
01730     LPWSTR usersid = NULL;
01731     LPWSTR targsid = NULL;
01732     WCHAR patch[GUID_SIZE];
01733     WCHAR targprod[GUID_SIZE];
01734     DWORD len;
01735     UINT r;
01736 
01737     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
01738           debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, dwFilter,
01739           dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
01740           szTargetUserSid, pcchTargetUserSid);
01741 
01742     if (szTargetUserSid && !pcchTargetUserSid)
01743         return ERROR_INVALID_PARAMETER;
01744 
01745     if (szProductCode) prodcode = strdupAtoW(szProductCode);
01746     if (szUserSid) usersid = strdupAtoW(szUserSid);
01747 
01748     r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
01749                           patch, targprod, pdwTargetProductContext,
01750                           NULL, &len);
01751     if (r != ERROR_SUCCESS)
01752         goto done;
01753 
01754     WideCharToMultiByte(CP_ACP, 0, patch, -1, szPatchCode,
01755                         GUID_SIZE, NULL, NULL);
01756     WideCharToMultiByte(CP_ACP, 0, targprod, -1, szTargetProductCode,
01757                         GUID_SIZE, NULL, NULL);
01758 
01759     if (!szTargetUserSid)
01760     {
01761         if (pcchTargetUserSid)
01762             *pcchTargetUserSid = len;
01763 
01764         goto done;
01765     }
01766 
01767     targsid = msi_alloc(++len * sizeof(WCHAR));
01768     if (!targsid)
01769     {
01770         r = ERROR_OUTOFMEMORY;
01771         goto done;
01772     }
01773 
01774     r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
01775                           patch, targprod, pdwTargetProductContext,
01776                           targsid, &len);
01777     if (r != ERROR_SUCCESS || !szTargetUserSid)
01778         goto done;
01779 
01780     WideCharToMultiByte(CP_ACP, 0, targsid, -1, szTargetUserSid,
01781                         *pcchTargetUserSid, NULL, NULL);
01782 
01783     len = lstrlenW(targsid);
01784     if (*pcchTargetUserSid < len + 1)
01785     {
01786         r = ERROR_MORE_DATA;
01787         *pcchTargetUserSid = len * sizeof(WCHAR);
01788     }
01789     else
01790         *pcchTargetUserSid = len;
01791 
01792 done:
01793     msi_free(prodcode);
01794     msi_free(usersid);
01795     msi_free(targsid);
01796 
01797     return r;
01798 }
01799 
01800 static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
01801                                 MSIINSTALLCONTEXT context,
01802                                 LPWSTR patch, MSIPATCHSTATE *state)
01803 {
01804     DWORD type, val, size;
01805     HKEY prod, hkey = 0;
01806     HKEY udpatch = 0;
01807     LONG res;
01808     UINT r = ERROR_NO_MORE_ITEMS;
01809 
01810     *state = MSIPATCHSTATE_INVALID;
01811 
01812     r = MSIREG_OpenUserDataProductKey(prodcode, context,
01813                                       usersid, &prod, FALSE);
01814     if (r != ERROR_SUCCESS)
01815         return ERROR_NO_MORE_ITEMS;
01816 
01817     res = RegOpenKeyExW(prod, szPatches, 0, KEY_READ, &hkey);
01818     if (res != ERROR_SUCCESS)
01819         goto done;
01820 
01821     res = RegOpenKeyExW(hkey, patch, 0, KEY_READ, &udpatch);
01822     if (res != ERROR_SUCCESS)
01823         goto done;
01824 
01825     size = sizeof(DWORD);
01826     res = RegGetValueW(udpatch, NULL, szState, RRF_RT_DWORD, &type, &val, &size);
01827     if (res != ERROR_SUCCESS ||
01828         val < MSIPATCHSTATE_APPLIED || val > MSIPATCHSTATE_REGISTERED)
01829     {
01830         r = ERROR_BAD_CONFIGURATION;
01831         goto done;
01832     }
01833 
01834     *state = val;
01835     r = ERROR_SUCCESS;
01836 
01837 done:
01838     RegCloseKey(udpatch);
01839     RegCloseKey(hkey);
01840     RegCloseKey(prod);
01841 
01842     return r;
01843 }
01844 
01845 static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
01846         MSIINSTALLCONTEXT context, DWORD filter, DWORD index, DWORD *idx,
01847         LPWSTR patch, LPWSTR targetprod, MSIINSTALLCONTEXT *targetctx,
01848         LPWSTR targetsid, DWORD *sidsize, LPWSTR *transforms)
01849 {
01850     MSIPATCHSTATE state = MSIPATCHSTATE_INVALID;
01851     LPWSTR ptr, patches = NULL;
01852     HKEY prod, patchkey = 0;
01853     HKEY localprod = 0, localpatch = 0;
01854     DWORD type, size;
01855     LONG res;
01856     UINT temp, r = ERROR_NO_MORE_ITEMS;
01857 
01858     if (MSIREG_OpenProductKey(prodcode, usersid, context,
01859                               &prod, FALSE) != ERROR_SUCCESS)
01860         return ERROR_NO_MORE_ITEMS;
01861 
01862     size = 0;
01863     res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type, NULL,
01864                        &size);
01865     if (res != ERROR_SUCCESS)
01866         goto done;
01867 
01868     if (type != REG_MULTI_SZ)
01869     {
01870         r = ERROR_BAD_CONFIGURATION;
01871         goto done;
01872     }
01873 
01874     patches = msi_alloc(size);
01875     if (!patches)
01876     {
01877         r = ERROR_OUTOFMEMORY;
01878         goto done;
01879     }
01880 
01881     res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type,
01882                        patches, &size);
01883     if (res != ERROR_SUCCESS)
01884         goto done;
01885 
01886     for (ptr = patches; *ptr && r == ERROR_NO_MORE_ITEMS; ptr += lstrlenW(ptr) + 1)
01887     {
01888         if (!unsquash_guid(ptr, patch))
01889         {
01890             r = ERROR_BAD_CONFIGURATION;
01891             goto done;
01892         }
01893 
01894         size = 0;
01895         res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
01896                            &type, NULL, &size);
01897         if (res != ERROR_SUCCESS)
01898             continue;
01899 
01900         if (transforms)
01901         {
01902             *transforms = msi_alloc(size);
01903             if (!*transforms)
01904             {
01905                 r = ERROR_OUTOFMEMORY;
01906                 goto done;
01907             }
01908 
01909             res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
01910                                &type, *transforms, &size);
01911             if (res != ERROR_SUCCESS)
01912                 continue;
01913         }
01914 
01915         if (context == MSIINSTALLCONTEXT_USERMANAGED)
01916         {
01917             if (!(filter & MSIPATCHSTATE_APPLIED))
01918             {
01919                 temp = msi_get_patch_state(prodcode, usersid, context,
01920                                            ptr, &state);
01921                 if (temp == ERROR_BAD_CONFIGURATION)
01922                 {
01923                     r = ERROR_BAD_CONFIGURATION;
01924                     goto done;
01925                 }
01926 
01927                 if (temp != ERROR_SUCCESS || !(filter & state))
01928                     continue;
01929             }
01930         }
01931         else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
01932         {
01933             if (!(filter & MSIPATCHSTATE_APPLIED))
01934             {
01935                 temp = msi_get_patch_state(prodcode, usersid, context,
01936                                            ptr, &state);
01937                 if (temp == ERROR_BAD_CONFIGURATION)
01938                 {
01939                     r = ERROR_BAD_CONFIGURATION;
01940                     goto done;
01941                 }
01942 
01943                 if (temp != ERROR_SUCCESS || !(filter & state))
01944                     continue;
01945             }
01946             else
01947             {
01948                 temp = MSIREG_OpenUserDataPatchKey(patch, context,
01949                                                    &patchkey, FALSE);
01950                 RegCloseKey(patchkey);
01951                 if (temp != ERROR_SUCCESS)
01952                     continue;
01953             }
01954         }
01955         else if (context == MSIINSTALLCONTEXT_MACHINE)
01956         {
01957             usersid = szEmpty;
01958 
01959             if (MSIREG_OpenUserDataProductKey(prodcode, context, NULL, &localprod, FALSE) == ERROR_SUCCESS &&
01960                 RegOpenKeyExW(localprod, szPatches, 0, KEY_READ, &localpatch) == ERROR_SUCCESS &&
01961                 RegOpenKeyExW(localpatch, ptr, 0, KEY_READ, &patchkey) == ERROR_SUCCESS)
01962             {
01963                 res = RegGetValueW(patchkey, NULL, szState, RRF_RT_REG_DWORD,
01964                                    &type, &state, &size);
01965 
01966                 if (!(filter & state))
01967                     res = ERROR_NO_MORE_ITEMS;
01968 
01969                 RegCloseKey(patchkey);
01970             }
01971 
01972             RegCloseKey(localpatch);
01973             RegCloseKey(localprod);
01974 
01975             if (res != ERROR_SUCCESS)
01976                 continue;
01977         }
01978 
01979         if (*idx < index)
01980         {
01981             (*idx)++;
01982             continue;
01983         }
01984 
01985         r = ERROR_SUCCESS;
01986         if (targetprod)
01987             lstrcpyW(targetprod, prodcode);
01988 
01989         if (targetctx)
01990             *targetctx = context;
01991 
01992         if (targetsid)
01993         {
01994             lstrcpynW(targetsid, usersid, *sidsize);
01995             if (lstrlenW(usersid) >= *sidsize)
01996                 r = ERROR_MORE_DATA;
01997         }
01998 
01999         if (sidsize)
02000         {
02001             *sidsize = lstrlenW(usersid);
02002             if (!targetsid)
02003                 *sidsize *= sizeof(WCHAR);
02004         }
02005     }
02006 
02007 done:
02008     RegCloseKey(prod);
02009     msi_free(patches);
02010 
02011     return r;
02012 }
02013 
02014 static UINT msi_enum_patches(LPCWSTR szProductCode, LPCWSTR szUserSid,
02015         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, DWORD *idx,
02016         LPWSTR szPatchCode, LPWSTR szTargetProductCode,
02017         MSIINSTALLCONTEXT *pdwTargetProductContext, LPWSTR szTargetUserSid,
02018         LPDWORD pcchTargetUserSid, LPWSTR *szTransforms)
02019 {
02020     LPWSTR usersid = NULL;
02021     UINT r = ERROR_INVALID_PARAMETER;
02022 
02023     if (!szUserSid)
02024     {
02025         szUserSid = usersid = get_user_sid();
02026         if (!usersid) return ERROR_FUNCTION_FAILED;
02027     }
02028 
02029     if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
02030     {
02031         r = msi_check_product_patches(szProductCode, szUserSid,
02032                                       MSIINSTALLCONTEXT_USERMANAGED, dwFilter,
02033                                       dwIndex, idx, szPatchCode,
02034                                       szTargetProductCode,
02035                                       pdwTargetProductContext, szTargetUserSid,
02036                                       pcchTargetUserSid, szTransforms);
02037         if (r != ERROR_NO_MORE_ITEMS)
02038             goto done;
02039     }
02040 
02041     if (dwContext & MSIINSTALLCONTEXT_USERUNMANAGED)
02042     {
02043         r = msi_check_product_patches(szProductCode, szUserSid,
02044                                       MSIINSTALLCONTEXT_USERUNMANAGED, dwFilter,
02045                                       dwIndex, idx, szPatchCode,
02046                                       szTargetProductCode,
02047                                       pdwTargetProductContext, szTargetUserSid,
02048                                       pcchTargetUserSid, szTransforms);
02049         if (r != ERROR_NO_MORE_ITEMS)
02050             goto done;
02051     }
02052 
02053     if (dwContext & MSIINSTALLCONTEXT_MACHINE)
02054     {
02055         r = msi_check_product_patches(szProductCode, szUserSid,
02056                                       MSIINSTALLCONTEXT_MACHINE, dwFilter,
02057                                       dwIndex, idx, szPatchCode,
02058                                       szTargetProductCode,
02059                                       pdwTargetProductContext, szTargetUserSid,
02060                                       pcchTargetUserSid, szTransforms);
02061         if (r != ERROR_NO_MORE_ITEMS)
02062             goto done;
02063     }
02064 
02065 done:
02066     LocalFree(usersid);
02067     return r;
02068 }
02069 
02070 /***********************************************************************
02071  * MsiEnumPatchesExW            [MSI.@]
02072  */
02073 UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
02074         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPWSTR szPatchCode,
02075         LPWSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
02076         LPWSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
02077 {
02078     WCHAR squished_pc[GUID_SIZE];
02079     DWORD idx = 0;
02080     UINT r;
02081 
02082     static DWORD last_index;
02083 
02084     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
02085           debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter,
02086           dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
02087           szTargetUserSid, pcchTargetUserSid);
02088 
02089     if (!szProductCode || !squash_guid(szProductCode, squished_pc))
02090         return ERROR_INVALID_PARAMETER;
02091 
02092     if (szUserSid && !strcmpW( szUserSid, szLocalSid ))
02093         return ERROR_INVALID_PARAMETER;
02094 
02095     if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
02096         return ERROR_INVALID_PARAMETER;
02097 
02098     if (dwContext <= MSIINSTALLCONTEXT_NONE ||
02099         dwContext > MSIINSTALLCONTEXT_ALL)
02100         return ERROR_INVALID_PARAMETER;
02101 
02102     if (dwFilter <= MSIPATCHSTATE_INVALID || dwFilter > MSIPATCHSTATE_ALL)
02103         return ERROR_INVALID_PARAMETER;
02104 
02105     if (dwIndex && dwIndex - last_index != 1)
02106         return ERROR_INVALID_PARAMETER;
02107 
02108     if (dwIndex == 0)
02109         last_index = 0;
02110 
02111     r = msi_enum_patches(szProductCode, szUserSid, dwContext, dwFilter,
02112                          dwIndex, &idx, szPatchCode, szTargetProductCode,
02113                          pdwTargetProductContext, szTargetUserSid,
02114                          pcchTargetUserSid, NULL);
02115 
02116     if (r == ERROR_SUCCESS)
02117         last_index = dwIndex;
02118     else
02119         last_index = 0;
02120 
02121     return r;
02122 }
02123 
02124 /***********************************************************************
02125  * MsiEnumPatchesA            [MSI.@]
02126  */
02127 UINT WINAPI MsiEnumPatchesA(LPCSTR szProduct, DWORD iPatchIndex,
02128         LPSTR lpPatchBuf, LPSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
02129 {
02130     LPWSTR product, transforms;
02131     WCHAR patch[GUID_SIZE];
02132     DWORD len;
02133     UINT r;
02134 
02135     TRACE("(%s %d %p %p %p)\n", debugstr_a(szProduct), iPatchIndex,
02136           lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
02137 
02138     if (!szProduct || !lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
02139         return ERROR_INVALID_PARAMETER;
02140 
02141     product = strdupAtoW(szProduct);
02142     if (!product)
02143         return ERROR_OUTOFMEMORY;
02144 
02145     len = *pcchTransformsBuf;
02146     transforms = msi_alloc( len * sizeof(WCHAR) );
02147     if (!transforms)
02148     {
02149         r = ERROR_OUTOFMEMORY;
02150         goto done;
02151     }
02152 
02153     r = MsiEnumPatchesW(product, iPatchIndex, patch, transforms, &len);
02154     if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
02155         goto done;
02156 
02157     WideCharToMultiByte(CP_ACP, 0, patch, -1, lpPatchBuf,
02158                         GUID_SIZE, NULL, NULL);
02159 
02160     if (!WideCharToMultiByte(CP_ACP, 0, transforms, -1, lpTransformsBuf,
02161                              *pcchTransformsBuf, NULL, NULL))
02162         r = ERROR_MORE_DATA;
02163 
02164     if (r == ERROR_MORE_DATA)
02165     {
02166         lpTransformsBuf[*pcchTransformsBuf - 1] = '\0';
02167         *pcchTransformsBuf = len * 2;
02168     }
02169     else
02170         *pcchTransformsBuf = strlen( lpTransformsBuf );
02171 
02172 done:
02173     msi_free(transforms);
02174     msi_free(product);
02175 
02176     return r;
02177 }
02178 
02179 /***********************************************************************
02180  * MsiEnumPatchesW            [MSI.@]
02181  */
02182 UINT WINAPI MsiEnumPatchesW(LPCWSTR szProduct, DWORD iPatchIndex,
02183         LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
02184 {
02185     WCHAR squished_pc[GUID_SIZE];
02186     LPWSTR transforms = NULL;
02187     HKEY prod;
02188     DWORD idx = 0;
02189     UINT r;
02190 
02191     TRACE("(%s %d %p %p %p)\n", debugstr_w(szProduct), iPatchIndex,
02192           lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
02193 
02194     if (!szProduct || !squash_guid(szProduct, squished_pc))
02195         return ERROR_INVALID_PARAMETER;
02196 
02197     if (!lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
02198         return ERROR_INVALID_PARAMETER;
02199 
02200     if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
02201                               &prod, FALSE) != ERROR_SUCCESS &&
02202         MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
02203                               &prod, FALSE) != ERROR_SUCCESS &&
02204         MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
02205                               &prod, FALSE) != ERROR_SUCCESS)
02206         return ERROR_UNKNOWN_PRODUCT;
02207 
02208     RegCloseKey(prod);
02209 
02210     r = msi_enum_patches(szProduct, NULL, MSIINSTALLCONTEXT_ALL,
02211                          MSIPATCHSTATE_ALL, iPatchIndex, &idx, lpPatchBuf,
02212                          NULL, NULL, NULL, NULL, &transforms);
02213     if (r != ERROR_SUCCESS)
02214         goto done;
02215 
02216     lstrcpynW(lpTransformsBuf, transforms, *pcchTransformsBuf);
02217     if (*pcchTransformsBuf <= lstrlenW(transforms))
02218     {
02219         r = ERROR_MORE_DATA;
02220         *pcchTransformsBuf = lstrlenW(transforms);
02221     }
02222     else
02223         *pcchTransformsBuf = lstrlenW(transforms);
02224 
02225 done:
02226     msi_free(transforms);
02227     return r;
02228 }
02229 
02230 UINT WINAPI MsiEnumProductsExA( LPCSTR product, LPCSTR usersid, DWORD ctx, DWORD index,
02231                                 CHAR installed_product[GUID_SIZE],
02232                                 MSIINSTALLCONTEXT *installed_ctx, LPSTR sid, LPDWORD sid_len )
02233 {
02234     UINT r;
02235     WCHAR installed_productW[GUID_SIZE], *productW = NULL, *usersidW = NULL, *sidW = NULL;
02236 
02237     TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_a(product), debugstr_a(usersid),
02238           ctx, index, installed_product, installed_ctx, sid, sid_len);
02239 
02240     if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
02241     if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
02242     if (usersid && !(usersidW = strdupAtoW( usersid )))
02243     {
02244         msi_free( productW );
02245         return ERROR_OUTOFMEMORY;
02246     }
02247     if (sid && !(sidW = msi_alloc( *sid_len * sizeof(WCHAR) )))
02248     {
02249         msi_free( usersidW );
02250         msi_free( productW );
02251         return ERROR_OUTOFMEMORY;
02252     }
02253     r = MsiEnumProductsExW( productW, usersidW, ctx, index, installed_productW,
02254                             installed_ctx, sidW, sid_len );
02255     if (r == ERROR_SUCCESS)
02256     {
02257         if (installed_product) WideCharToMultiByte( CP_ACP, 0, installed_productW, GUID_SIZE,
02258                                                     installed_product, GUID_SIZE, NULL, NULL );
02259         if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
02260     }
02261     msi_free( productW );
02262     msi_free( usersidW );
02263     msi_free( sidW );
02264     return r;
02265 }
02266 
02267 static UINT fetch_machine_product( const WCHAR *match, DWORD index, DWORD *idx,
02268                                    WCHAR installed_product[GUID_SIZE],
02269                                    MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
02270 {
02271     static const WCHAR productsW[] =
02272         {'S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s','\\',
02273          'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
02274     UINT r;
02275     WCHAR product[GUID_SIZE];
02276     DWORD i = 0, len;
02277     REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
02278     HKEY key;
02279 
02280     if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, productsW, 0, access, &key ))
02281         return ERROR_NO_MORE_ITEMS;
02282 
02283     len = sizeof(product)/sizeof(product[0]);
02284     while (!RegEnumKeyExW( key, i, product, &len, NULL, NULL, NULL, NULL ))
02285     {
02286         if (match && strcmpW( match, product ))
02287         {
02288             i++;
02289             len = sizeof(product)/sizeof(product[0]);
02290             continue;
02291         }
02292         if (*idx == index) goto found;
02293         (*idx)++;
02294         len = sizeof(product)/sizeof(product[0]);
02295         i++;
02296     }
02297     RegCloseKey( key );
02298     return ERROR_NO_MORE_ITEMS;
02299 
02300 found:
02301     if (sid_len && *sid_len < 1)
02302     {
02303         *sid_len = 1;
02304         r = ERROR_MORE_DATA;
02305     }
02306     else
02307     {
02308         if (installed_product) unsquash_guid( product, installed_product );
02309         if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
02310         if (sid)
02311         {
02312             sid[0] = 0;
02313             *sid_len = 0;
02314         }
02315         r = ERROR_SUCCESS;
02316     }
02317     RegCloseKey( key );
02318     return r;
02319 }
02320 
02321 static UINT fetch_user_product( const WCHAR *match, const WCHAR *usersid, DWORD ctx, DWORD index,
02322                                 DWORD *idx, WCHAR installed_product[GUID_SIZE],
02323                                 MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
02324 {
02325     static const WCHAR managedW[] =
02326         {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
02327          'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s',
02328          'i','o','n','\\','I','n','s','t','a','l','l','e','r','\\','M','a','n','a','g','e','d',0};
02329     static const WCHAR managed_productsW[] =
02330         {'\\','I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
02331     static const WCHAR unmanaged_productsW[] =
02332         {'\\','S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
02333          'I','n','s','t','a','l','l','e','r','\\','P','r','o','d','u','c','t','s',0};
02334     UINT r;
02335     const WCHAR *subkey;
02336     WCHAR path[MAX_PATH], product[GUID_SIZE], user[128];
02337     DWORD i = 0, j = 0, len_product, len_user;
02338     REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
02339     HKEY key_users, key_products;
02340 
02341     if (ctx == MSIINSTALLCONTEXT_USERMANAGED)
02342     {
02343         subkey = managed_productsW;
02344         if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, managedW, 0, access, &key_users ))
02345             return ERROR_NO_MORE_ITEMS;
02346     }
02347     else if (ctx == MSIINSTALLCONTEXT_USERUNMANAGED)
02348     {
02349         subkey = unmanaged_productsW;
02350         if (RegOpenKeyExW( HKEY_USERS, NULL, 0, access, &key_users ))
02351             return ERROR_NO_MORE_ITEMS;
02352     }
02353     else return ERROR_INVALID_PARAMETER;
02354 
02355     len_user = sizeof(user)/sizeof(user[0]);
02356     while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
02357     {
02358         if (strcmpW( usersid, user ) && strcmpW( usersid, szAllSid ))
02359         {
02360             i++;
02361             len_user = sizeof(user)/sizeof(user[0]);
02362             continue;
02363         }
02364         strcpyW( path, user );
02365         strcatW( path, subkey );
02366         if (RegOpenKeyExW( key_users, path, 0, access, &key_products ))
02367         {
02368             i++;
02369             len_user = sizeof(user)/sizeof(user[0]);
02370             continue;
02371         }
02372         len_product = sizeof(product)/sizeof(product[0]);
02373         while (!RegEnumKeyExW( key_products, j, product, &len_product, NULL, NULL, NULL, NULL ))
02374         {
02375             if (match && strcmpW( match, product ))
02376             {
02377                 j++;
02378                 len_product = sizeof(product)/sizeof(product[0]);
02379                 continue;
02380             }
02381             if (*idx == index) goto found;
02382             (*idx)++;
02383             len_product = sizeof(product)/sizeof(product[0]);
02384             j++;
02385         }
02386         RegCloseKey( key_products );
02387         len_user = sizeof(user)/sizeof(user[0]);
02388         i++;
02389     }
02390     RegCloseKey( key_users );
02391     return ERROR_NO_MORE_ITEMS;
02392 
02393 found:
02394     if (sid_len && *sid_len <= len_user)
02395     {
02396         *sid_len = len_user;
02397         r = ERROR_MORE_DATA;
02398     }
02399     else
02400     {
02401         if (installed_product) unsquash_guid( product, installed_product );
02402         if (installed_ctx) *installed_ctx = ctx;
02403         if (sid)
02404         {
02405             strcpyW( sid, user );
02406             *sid_len = len_user;
02407         }
02408         r = ERROR_SUCCESS;
02409     }
02410     RegCloseKey( key_products );
02411     RegCloseKey( key_users );
02412     return r;
02413 }
02414 
02415 static UINT enum_products( const WCHAR *product, const WCHAR *usersid, DWORD ctx, DWORD index,
02416                            DWORD *idx, WCHAR installed_product[GUID_SIZE],
02417                            MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
02418 {
02419     UINT r = ERROR_NO_MORE_ITEMS;
02420     WCHAR *user = NULL;
02421 
02422     if (!usersid)
02423     {
02424         usersid = user = get_user_sid();
02425         if (!user) return ERROR_FUNCTION_FAILED;
02426     }
02427     if (ctx & MSIINSTALLCONTEXT_MACHINE)
02428     {
02429         r = fetch_machine_product( product, index, idx, installed_product, installed_ctx,
02430                                    sid, sid_len );
02431         if (r != ERROR_NO_MORE_ITEMS) goto done;
02432     }
02433     if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
02434     {
02435         r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index,
02436                                 idx, installed_product, installed_ctx, sid, sid_len );
02437         if (r != ERROR_NO_MORE_ITEMS) goto done;
02438     }
02439     if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
02440     {
02441         r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERMANAGED, index,
02442                                 idx, installed_product, installed_ctx, sid, sid_len );
02443         if (r != ERROR_NO_MORE_ITEMS) goto done;
02444     }
02445 
02446 done:
02447     LocalFree( user );
02448     return r;
02449 }
02450 
02451 UINT WINAPI MsiEnumProductsExW( LPCWSTR product, LPCWSTR usersid, DWORD ctx, DWORD index,
02452                                 WCHAR installed_product[GUID_SIZE],
02453                                 MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
02454 {
02455     UINT r;
02456     DWORD idx = 0;
02457     static DWORD last_index;
02458 
02459     TRACE("%s, %s, %u, %u, %p, %p, %p, %p\n", debugstr_w(product), debugstr_w(usersid),
02460           ctx, index, installed_product, installed_ctx, sid, sid_len);
02461 
02462     if ((sid && !sid_len) || !ctx || (usersid && ctx == MSIINSTALLCONTEXT_MACHINE))
02463         return ERROR_INVALID_PARAMETER;
02464 
02465     if (index && index - last_index != 1)
02466         return ERROR_INVALID_PARAMETER;
02467 
02468     if (!index) last_index = 0;
02469 
02470     r = enum_products( product, usersid, ctx, index, &idx, installed_product, installed_ctx,
02471                        sid, sid_len );
02472     if (r == ERROR_SUCCESS)
02473         last_index = index;
02474     else
02475         last_index = 0;
02476 
02477     return r;
02478 }

Generated on Sat May 26 2012 04:16:03 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.