Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenregistry.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
1.7.6.1
|