~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/msi/registry.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Implementation of the Microsoft Installer (msi.dll)
  3  *
  4  * Copyright 2005 Mike McCormack for CodeWeavers
  5  * Copyright 2005 Aric Stewart for CodeWeavers
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 #include <stdarg.h>
 23 
 24 #define COBJMACROS
 25 #define NONAMELESSUNION
 26 
 27 #include "windef.h"
 28 #include "winbase.h"
 29 #include "winreg.h"
 30 #include "winnls.h"
 31 #include "shlwapi.h"
 32 #include "wine/debug.h"
 33 #include "msi.h"
 34 #include "msipriv.h"
 35 #include "wincrypt.h"
 36 #include "wine/unicode.h"
 37 #include "winver.h"
 38 #include "winuser.h"
 39 #include "sddl.h"
 40 
 41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 42 
 43 
 44 /* 
 45  * This module will be all the helper functions for registry access by the
 46  * installer bits. 
 47  */
 48 static const WCHAR szUserFeatures_fmt[] = {
 49 'S','o','f','t','w','a','r','e','\\',
 50 'M','i','c','r','o','s','o','f','t','\\',
 51 'I','n','s','t','a','l','l','e','r','\\',
 52 'F','e','a','t','u','r','e','s','\\',
 53 '%','s',0};
 54 
 55 static const WCHAR szUserDataFeatures_fmt[] = {
 56 'S','o','f','t','w','a','r','e','\\',
 57 'M','i','c','r','o','s','o','f','t','\\',
 58 'W','i','n','d','o','w','s','\\',
 59 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
 60 'I','n','s','t','a','l','l','e','r','\\',
 61 'U','s','e','r','D','a','t','a','\\',
 62 '%','s','\\','P','r','o','d','u','c','t','s','\\',
 63 '%','s','\\','F','e','a','t','u','r','e','s',0};
 64 
 65 static const WCHAR szInstaller_Features_fmt[] = {
 66 'S','o','f','t','w','a','r','e','\\',
 67 'M','i','c','r','o','s','o','f','t','\\',
 68 'W','i','n','d','o','w','s','\\',
 69 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
 70 'I','n','s','t','a','l','l','e','r','\\',
 71 'F','e','a','t','u','r','e','s','\\',
 72 '%','s',0};
 73 
 74 static const WCHAR szInstaller_Components[] = {
 75 'S','o','f','t','w','a','r','e','\\',
 76 'M','i','c','r','o','s','o','f','t','\\',
 77 'W','i','n','d','o','w','s','\\',
 78 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
 79 'I','n','s','t','a','l','l','e','r','\\',
 80 'C','o','m','p','o','n','e','n','t','s',0 };
 81 
 82 static const WCHAR szUser_Components_fmt[] = {
 83 'S','o','f','t','w','a','r','e','\\',
 84 'M','i','c','r','o','s','o','f','t','\\',
 85 'I','n','s','t','a','l','l','e','r','\\',
 86 'C','o','m','p','o','n','e','n','t','s','\\',
 87 '%','s',0};
 88 
 89 static const WCHAR szUserDataComp_fmt[] = {
 90 'S','o','f','t','w','a','r','e','\\',
 91 'M','i','c','r','o','s','o','f','t','\\',
 92 'W','i','n','d','o','w','s','\\',
 93 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
 94 'I','n','s','t','a','l','l','e','r','\\',
 95 'U','s','e','r','D','a','t','a','\\',
 96 '%','s','\\','C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
 97 
 98 static const WCHAR szUninstall_fmt[] = {
 99 'S','o','f','t','w','a','r','e','\\',
100 'M','i','c','r','o','s','o','f','t','\\',
101 'W','i','n','d','o','w','s','\\',
102 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
103 'U','n','i','n','s','t','a','l','l','\\',
104 '%','s',0 };
105 
106 static const WCHAR szUserProduct_fmt[] = {
107 'S','o','f','t','w','a','r','e','\\',
108 'M','i','c','r','o','s','o','f','t','\\',
109 'I','n','s','t','a','l','l','e','r','\\',
110 'P','r','o','d','u','c','t','s','\\',
111 '%','s',0};
112 
113 static const WCHAR szUserPatch_fmt[] = {
114 'S','o','f','t','w','a','r','e','\\',
115 'M','i','c','r','o','s','o','f','t','\\',
116 'I','n','s','t','a','l','l','e','r','\\',
117 'P','a','t','c','h','e','s','\\',
118 '%','s',0};
119 
120 static const WCHAR szInstaller_Products[] = {
121 'S','o','f','t','w','a','r','e','\\',
122 'M','i','c','r','o','s','o','f','t','\\',
123 'W','i','n','d','o','w','s','\\',
124 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
125 'I','n','s','t','a','l','l','e','r','\\',
126 'P','r','o','d','u','c','t','s',0};
127 
128 static const WCHAR szInstaller_Products_fmt[] = {
129 'S','o','f','t','w','a','r','e','\\',
130 'M','i','c','r','o','s','o','f','t','\\',
131 'W','i','n','d','o','w','s','\\',
132 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
133 'I','n','s','t','a','l','l','e','r','\\',
134 'P','r','o','d','u','c','t','s','\\',
135 '%','s',0};
136 
137 static const WCHAR szInstaller_Patches_fmt[] = {
138 'S','o','f','t','w','a','r','e','\\',
139 'M','i','c','r','o','s','o','f','t','\\',
140 'W','i','n','d','o','w','s','\\',
141 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
142 'I','n','s','t','a','l','l','e','r','\\',
143 'P','a','t','c','h','e','s','\\',
144 '%','s',0};
145 
146 static const WCHAR szInstaller_UpgradeCodes_fmt[] = {
147 'S','o','f','t','w','a','r','e','\\',
148 'M','i','c','r','o','s','o','f','t','\\',
149 'W','i','n','d','o','w','s','\\',
150 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
151 'I','n','s','t','a','l','l','e','r','\\',
152 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
153 '%','s',0};
154 
155 static const WCHAR szInstaller_UserUpgradeCodes_fmt[] = {
156 'S','o','f','t','w','a','r','e','\\',
157 'M','i','c','r','o','s','o','f','t','\\',
158 'I','n','s','t','a','l','l','e','r','\\',
159 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
160 '%','s',0};
161 
162 static const WCHAR szUserDataProd_fmt[] = {
163 'S','o','f','t','w','a','r','e','\\',
164 'M','i','c','r','o','s','o','f','t','\\',
165 'W','i','n','d','o','w','s','\\',
166 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
167 'I','n','s','t','a','l','l','e','r','\\',
168 'U','s','e','r','D','a','t','a','\\',
169 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
170 
171 static const WCHAR szUserDataPatch_fmt[] = {
172 'S','o','f','t','w','a','r','e','\\',
173 'M','i','c','r','o','s','o','f','t','\\',
174 'W','i','n','d','o','w','s','\\',
175 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
176 'I','n','s','t','a','l','l','e','r','\\',
177 'U','s','e','r','D','a','t','a','\\',
178 '%','s','\\','P','a','t','c','h','e','s','\\','%','s',0};
179 
180 static const WCHAR szInstallProperties_fmt[] = {
181 'S','o','f','t','w','a','r','e','\\',
182 'M','i','c','r','o','s','o','f','t','\\',
183 'W','i','n','d','o','w','s','\\',
184 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
185 'I','n','s','t','a','l','l','e','r','\\',
186 'U','s','e','r','D','a','t','a','\\',
187 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
188 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
189 
190 static const WCHAR szInstaller_LocalClassesProd_fmt[] = {
191 'S','o','f','t','w','a','r','e','\\',
192 'C','l','a','s','s','e','s','\\',
193 'I','n','s','t','a','l','l','e','r','\\',
194 'P','r','o','d','u','c','t','s','\\','%','s',0};
195 
196 static const WCHAR szInstaller_LocalClassesFeat_fmt[] = {
197 'S','o','f','t','w','a','r','e','\\',
198 'C','l','a','s','s','e','s','\\',
199 'I','n','s','t','a','l','l','e','r','\\',
200 'F','e','a','t','u','r','e','s','\\','%','s',0};
201 
202 static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
203 'S','o','f','t','w','a','r','e','\\',
204 'M','i','c','r','o','s','o','f','t','\\',
205 'W','i','n','d','o','w','s','\\',
206 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
207 'I','n','s','t','a','l','l','e','r','\\',
208 'M','a','n','a','g','e','d','\\','%','s','\\',
209 'I','n','s','t','a','l','l','e','r','\\',
210 'P','r','o','d','u','c','t','s','\\','%','s',0};
211 
212 static const WCHAR szInstaller_LocalManagedFeat_fmt[] = {
213 'S','o','f','t','w','a','r','e','\\',
214 'M','i','c','r','o','s','o','f','t','\\',
215 'W','i','n','d','o','w','s','\\',
216 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
217 'I','n','s','t','a','l','l','e','r','\\',
218 'M','a','n','a','g','e','d','\\','%','s','\\',
219 'I','n','s','t','a','l','l','e','r','\\',
220 'F','e','a','t','u','r','e','s','\\','%','s',0};
221 
222 static const WCHAR szInstaller_ClassesUpgrade_fmt[] = {
223 'I','n','s','t','a','l','l','e','r','\\',
224 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
225 '%','s',0};
226 
227 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
228 {
229     DWORD i,n=0;
230 
231     if (lstrlenW(in) != 32)
232         return FALSE;
233 
234     out[n++]='{';
235     for(i=0; i<8; i++)
236         out[n++] = in[7-i];
237     out[n++]='-';
238     for(i=0; i<4; i++)
239         out[n++] = in[11-i];
240     out[n++]='-';
241     for(i=0; i<4; i++)
242         out[n++] = in[15-i];
243     out[n++]='-';
244     for(i=0; i<2; i++)
245     {
246         out[n++] = in[17+i*2];
247         out[n++] = in[16+i*2];
248     }
249     out[n++]='-';
250     for( ; i<8; i++)
251     {
252         out[n++] = in[17+i*2];
253         out[n++] = in[16+i*2];
254     }
255     out[n++]='}';
256     out[n]=0;
257     return TRUE;
258 }
259 
260 BOOL squash_guid(LPCWSTR in, LPWSTR out)
261 {
262     DWORD i,n=1;
263     GUID guid;
264 
265     out[0] = 0;
266 
267     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
268         return FALSE;
269 
270     for(i=0; i<8; i++)
271         out[7-i] = in[n++];
272     n++;
273     for(i=0; i<4; i++)
274         out[11-i] = in[n++];
275     n++;
276     for(i=0; i<4; i++)
277         out[15-i] = in[n++];
278     n++;
279     for(i=0; i<2; i++)
280     {
281         out[17+i*2] = in[n++];
282         out[16+i*2] = in[n++];
283     }
284     n++;
285     for( ; i<8; i++)
286     {
287         out[17+i*2] = in[n++];
288         out[16+i*2] = in[n++];
289     }
290     out[32]=0;
291     return TRUE;
292 }
293 
294 
295 /* tables for encoding and decoding base85 */
296 static const unsigned char table_dec85[0x80] = {
297 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
298 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
299 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
300 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
301 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
302 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
303 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
304 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
305 };
306 
307 static const char table_enc85[] =
308 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
309 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
310 "yz{}~";
311 
312 /*
313  *  Converts a base85 encoded guid into a GUID pointer
314  *  Base85 encoded GUIDs should be 20 characters long.
315  *
316  *  returns TRUE if successful, FALSE if not
317  */
318 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
319 {
320     DWORD i, val = 0, base = 1, *p;
321 
322     if (!str)
323         return FALSE;
324 
325     p = (DWORD*) guid;
326     for( i=0; i<20; i++ )
327     {
328         if( (i%5) == 0 )
329         {
330             val = 0;
331             base = 1;
332         }
333         val += table_dec85[str[i]] * base;
334         if( str[i] >= 0x80 )
335             return FALSE;
336         if( table_dec85[str[i]] == 0xff )
337             return FALSE;
338         if( (i%5) == 4 )
339             p[i/5] = val;
340         base *= 85;
341     }
342     return TRUE;
343 }
344 
345 /*
346  *  Encodes a base85 guid given a GUID pointer
347  *  Caller should provide a 21 character buffer for the encoded string.
348  *
349  *  returns TRUE if successful, FALSE if not
350  */
351 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
352 {
353     unsigned int x, *p, i;
354 
355     p = (unsigned int*) guid;
356     for( i=0; i<4; i++ )
357     {
358         x = p[i];
359         *str++ = table_enc85[x%85];
360         x = x/85;
361         *str++ = table_enc85[x%85];
362         x = x/85;
363         *str++ = table_enc85[x%85];
364         x = x/85;
365         *str++ = table_enc85[x%85];
366         x = x/85;
367         *str++ = table_enc85[x%85];
368     }
369     *str = 0;
370 
371     return TRUE;
372 }
373 
374 DWORD msi_version_str_to_dword(LPCWSTR p)
375 {
376     DWORD major, minor = 0, build = 0, version = 0;
377 
378     if (!p)
379         return version;
380 
381     major = atoiW(p);
382 
383     p = strchrW(p, '.');
384     if (p)
385     {
386         minor = atoiW(p+1);
387         p = strchrW(p+1, '.');
388         if (p)
389             build = atoiW(p+1);
390     }
391 
392     return MAKELONG(build, MAKEWORD(minor, major));
393 }
394 
395 LPWSTR msi_version_dword_to_str(DWORD version)
396 {
397     static const WCHAR fmt[] = { '%','u','.','%','u','.','%','u',0 };
398     LPWSTR str = msi_alloc(20);
399     sprintfW(str, fmt,
400              (version&0xff000000)>>24,
401              (version&0x00ff0000)>>16,
402               version&0x0000ffff);
403     return str;
404 }
405 
406 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
407 {
408     static const WCHAR emptyW[] = {0};
409     DWORD len;
410     if (!value) value = emptyW;
411     len = (lstrlenW(value) + 1) * sizeof (WCHAR);
412     return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
413 }
414 
415 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
416 {
417     LPCWSTR p = value;
418     while (*p) p += lstrlenW(p) + 1;
419     return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
420                            (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
421 }
422 
423 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
424 {
425     return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
426 }
427 
428 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
429 {
430     HKEY hsubkey = 0;
431     LONG r;
432 
433     r = RegCreateKeyW( hkey, path, &hsubkey );
434     if (r != ERROR_SUCCESS)
435         return r;
436     r = msi_reg_set_val_str( hsubkey, name, val );
437     RegCloseKey( hsubkey );
438     return r;
439 }
440 
441 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
442 {
443     DWORD len = 0;
444     LPWSTR val;
445     LONG r;
446 
447     r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
448     if (r != ERROR_SUCCESS)
449         return NULL;
450 
451     len += sizeof (WCHAR);
452     val = msi_alloc( len );
453     if (!val)
454         return NULL;
455     val[0] = 0;
456     RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
457     return val;
458 }
459 
460 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
461 {
462     DWORD type, len = sizeof (DWORD);
463     LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
464     return r == ERROR_SUCCESS && type == REG_DWORD;
465 }
466 
467 static UINT get_user_sid(LPWSTR *usersid)
468 {
469     HANDLE token;
470     BYTE buf[1024];
471     DWORD size;
472     PTOKEN_USER user;
473 
474     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
475         return ERROR_FUNCTION_FAILED;
476 
477     size = sizeof(buf);
478     if (!GetTokenInformation(token, TokenUser, buf, size, &size)) {
479         CloseHandle(token);
480         return ERROR_FUNCTION_FAILED;
481     }
482 
483     user = (PTOKEN_USER)buf;
484     if (!ConvertSidToStringSidW(user->User.Sid, usersid)) {
485         CloseHandle(token);
486         return ERROR_FUNCTION_FAILED;
487     }
488     CloseHandle(token);
489     return ERROR_SUCCESS;
490 }
491 
492 UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
493 {
494     UINT rc;
495     WCHAR keypath[0x200];
496     TRACE("%s\n",debugstr_w(szProduct));
497 
498     sprintfW(keypath,szUninstall_fmt,szProduct);
499 
500     if (create)
501         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
502     else
503         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
504 
505     return rc;
506 }
507 
508 UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct)
509 {
510     WCHAR keypath[0x200];
511     TRACE("%s\n",debugstr_w(szProduct));
512 
513     sprintfW(keypath,szUninstall_fmt,szProduct);
514 
515     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
516 }
517 
518 UINT MSIREG_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
519                            HKEY *key, BOOL create)
520 {
521     UINT r;
522     LPWSTR usersid;
523     HKEY root = HKEY_LOCAL_MACHINE;
524     WCHAR squished_pc[GUID_SIZE];
525     WCHAR keypath[MAX_PATH];
526 
527     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
528 
529     if (!squash_guid(szProduct, squished_pc))
530         return ERROR_FUNCTION_FAILED;
531 
532     TRACE("squished (%s)\n", debugstr_w(squished_pc));
533 
534     if (context == MSIINSTALLCONTEXT_MACHINE)
535     {
536         sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
537     }
538     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
539     {
540         root = HKEY_CURRENT_USER;
541         sprintfW(keypath, szUserProduct_fmt, squished_pc);
542     }
543     else
544     {
545         r = get_user_sid(&usersid);
546         if (r != ERROR_SUCCESS || !usersid)
547         {
548             ERR("Failed to retrieve user SID: %d\n", r);
549             return r;
550         }
551 
552         sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc);
553         LocalFree(usersid);
554     }
555 
556     if (create)
557         return RegCreateKeyW(root, keypath, key);
558 
559     return RegOpenKeyW(root, keypath, key);
560 }
561 
562 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
563 {
564     WCHAR squished_pc[GUID_SIZE];
565     WCHAR keypath[0x200];
566 
567     TRACE("%s\n",debugstr_w(szProduct));
568     if (!squash_guid(szProduct,squished_pc))
569         return ERROR_FUNCTION_FAILED;
570     TRACE("squished (%s)\n", debugstr_w(squished_pc));
571 
572     sprintfW(keypath,szUserProduct_fmt,squished_pc);
573 
574     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
575 }
576 
577 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
578 {
579     UINT rc;
580     WCHAR squished_pc[GUID_SIZE];
581     WCHAR keypath[0x200];
582 
583     TRACE("%s\n",debugstr_w(szPatch));
584     if (!squash_guid(szPatch,squished_pc))
585         return ERROR_FUNCTION_FAILED;
586     TRACE("squished (%s)\n", debugstr_w(squished_pc));
587 
588     sprintfW(keypath,szUserPatch_fmt,squished_pc);
589 
590     if (create)
591         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
592     else
593         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
594 
595     return rc;
596 }
597 
598 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
599                             HKEY *key, BOOL create)
600 {
601     UINT r;
602     LPWSTR usersid;
603     HKEY root = HKEY_LOCAL_MACHINE;
604     WCHAR squished_pc[GUID_SIZE];
605     WCHAR keypath[MAX_PATH];
606 
607     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
608 
609     if (!squash_guid(szProduct, squished_pc))
610         return ERROR_FUNCTION_FAILED;
611 
612     TRACE("squished (%s)\n", debugstr_w(squished_pc));
613 
614     if (context == MSIINSTALLCONTEXT_MACHINE)
615     {
616         sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
617     }
618     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
619     {
620         root = HKEY_CURRENT_USER;
621         sprintfW(keypath, szUserFeatures_fmt, squished_pc);
622     }
623     else
624     {
625         r = get_user_sid(&usersid);
626         if (r != ERROR_SUCCESS || !usersid)
627         {
628             ERR("Failed to retrieve user SID: %d\n", r);
629             return r;
630         }
631 
632         sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc);
633         LocalFree(usersid);
634     }
635 
636     if (create)
637         return RegCreateKeyW(root, keypath, key);
638 
639     return RegOpenKeyW(root, keypath, key);
640 }
641 
642 UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
643 {
644     WCHAR squished_pc[GUID_SIZE];
645     WCHAR keypath[0x200];
646 
647     TRACE("%s\n",debugstr_w(szProduct));
648     if (!squash_guid(szProduct,squished_pc))
649         return ERROR_FUNCTION_FAILED;
650     TRACE("squished (%s)\n", debugstr_w(squished_pc));
651 
652     sprintfW(keypath,szUserFeatures_fmt,squished_pc);
653     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
654 }
655 
656 static UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
657 {
658     UINT rc;
659     WCHAR squished_pc[GUID_SIZE];
660     WCHAR keypath[0x200];
661 
662     TRACE("%s\n",debugstr_w(szProduct));
663     if (!squash_guid(szProduct,squished_pc))
664         return ERROR_FUNCTION_FAILED;
665     TRACE("squished (%s)\n", debugstr_w(squished_pc));
666 
667     sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
668 
669     if (create)
670         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
671     else
672         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
673 
674     return rc;
675 }
676 
677 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
678                                     HKEY *key, BOOL create)
679 {
680     UINT r;
681     LPWSTR usersid;
682     WCHAR squished_pc[GUID_SIZE];
683     WCHAR keypath[0x200];
684 
685     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
686 
687     if (!squash_guid(szProduct, squished_pc))
688         return ERROR_FUNCTION_FAILED;
689 
690     TRACE("squished (%s)\n", debugstr_w(squished_pc));
691 
692     if (context == MSIINSTALLCONTEXT_MACHINE)
693     {
694         sprintfW(keypath, szUserDataFeatures_fmt, szLocalSid, squished_pc);
695     }
696     else
697     {
698         r = get_user_sid(&usersid);
699         if (r != ERROR_SUCCESS || !usersid)
700         {
701             ERR("Failed to retrieve user SID: %d\n", r);
702             return r;
703         }
704 
705         sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
706         LocalFree(usersid);
707     }
708 
709     if (create)
710         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
711 
712     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
713 }
714 
715 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
716 {
717     UINT rc;
718     WCHAR squished_cc[GUID_SIZE];
719     WCHAR keypath[0x200];
720 
721     TRACE("%s\n",debugstr_w(szComponent));
722     if (!squash_guid(szComponent,squished_cc))
723         return ERROR_FUNCTION_FAILED;
724     TRACE("squished (%s)\n", debugstr_w(squished_cc));
725 
726     sprintfW(keypath,szUser_Components_fmt,squished_cc);
727 
728     if (create)
729         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
730     else
731         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
732 
733     return rc;
734 }
735 
736 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid,
737                                      HKEY *key, BOOL create)
738 {
739     UINT rc;
740     WCHAR comp[GUID_SIZE];
741     WCHAR keypath[0x200];
742     LPWSTR usersid;
743 
744     TRACE("%s\n", debugstr_w(szComponent));
745     if (!squash_guid(szComponent, comp))
746         return ERROR_FUNCTION_FAILED;
747     TRACE("squished (%s)\n", debugstr_w(comp));
748 
749     if (!szUserSid)
750     {
751         rc = get_user_sid(&usersid);
752         if (rc != ERROR_SUCCESS || !usersid)
753         {
754             ERR("Failed to retrieve user SID: %d\n", rc);
755             return rc;
756         }
757 
758         sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
759         LocalFree(usersid);
760     }
761     else
762         sprintfW(keypath, szUserDataComp_fmt, szUserSid, comp);
763 
764     if (create)
765         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
766     else
767         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
768 
769     return rc;
770 }
771 
772 UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid)
773 {
774     UINT rc;
775     WCHAR comp[GUID_SIZE];
776     WCHAR keypath[0x200];
777     LPWSTR usersid;
778 
779     TRACE("%s\n", debugstr_w(szComponent));
780     if (!squash_guid(szComponent, comp))
781         return ERROR_FUNCTION_FAILED;
782     TRACE("squished (%s)\n", debugstr_w(comp));
783 
784     if (!szUserSid)
785     {
786         rc = get_user_sid(&usersid);
787         if (rc != ERROR_SUCCESS || !usersid)
788         {
789             ERR("Failed to retrieve user SID: %d\n", rc);
790             return rc;
791         }
792 
793         sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
794         LocalFree(usersid);
795     }
796     else
797         sprintfW(keypath, szUserDataComp_fmt, szUserSid, comp);
798 
799     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
800 }
801 
802 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext,
803                                    LPCWSTR szUserSid, HKEY *key, BOOL create)
804 {
805     UINT rc;
806     WCHAR squished_pc[GUID_SIZE];
807     WCHAR keypath[0x200];
808     LPWSTR usersid;
809 
810     TRACE("%s\n", debugstr_w(szProduct));
811     if (!squash_guid(szProduct, squished_pc))
812         return ERROR_FUNCTION_FAILED;
813     TRACE("squished (%s)\n", debugstr_w(squished_pc));
814 
815     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
816         sprintfW(keypath, szUserDataProd_fmt, szLocalSid, squished_pc);
817     else if (szUserSid)
818         sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
819     else
820     {
821         rc = get_user_sid(&usersid);
822         if (rc != ERROR_SUCCESS || !usersid)
823         {
824             ERR("Failed to retrieve user SID: %d\n", rc);
825             return rc;
826         }
827 
828         sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
829         LocalFree(usersid);
830     }
831 
832     if (create)
833         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
834     else
835         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
836 
837     return rc;
838 }
839 
840 UINT MSIREG_OpenUserDataPatchKey(LPCWSTR szPatch, MSIINSTALLCONTEXT dwContext,
841                                  HKEY *key, BOOL create)
842 {
843     UINT rc;
844     WCHAR squished_patch[GUID_SIZE];
845     WCHAR keypath[0x200];
846     LPWSTR usersid;
847 
848     TRACE("%s\n", debugstr_w(szPatch));
849     if (!squash_guid(szPatch, squished_patch))
850         return ERROR_FUNCTION_FAILED;
851     TRACE("squished (%s)\n", debugstr_w(squished_patch));
852 
853     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
854         sprintfW(keypath, szUserDataPatch_fmt, szLocalSid, squished_patch);
855     else
856     {
857         rc = get_user_sid(&usersid);
858         if (rc != ERROR_SUCCESS || !usersid)
859         {
860             ERR("Failed to retrieve user SID: %d\n", rc);
861             return rc;
862         }
863 
864         sprintfW(keypath, szUserDataPatch_fmt, usersid, squished_patch);
865         LocalFree(usersid);
866     }
867 
868     if (create)
869         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
870 
871     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
872 }
873 
874 UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext,
875                              LPCWSTR szUserSid, HKEY *key, BOOL create)
876 {
877     UINT rc;
878     LPWSTR usersid;
879     WCHAR squished_pc[GUID_SIZE];
880     WCHAR keypath[0x200];
881 
882     TRACE("%s\n", debugstr_w(szProduct));
883     if (!squash_guid(szProduct, squished_pc))
884         return ERROR_FUNCTION_FAILED;
885     TRACE("squished (%s)\n", debugstr_w(squished_pc));
886 
887     if (dwContext == MSIINSTALLCONTEXT_MACHINE)
888         sprintfW(keypath, szInstallProperties_fmt, szLocalSid, squished_pc);
889     else if (szUserSid)
890         sprintfW(keypath, szInstallProperties_fmt, szUserSid, squished_pc);
891     else
892     {
893         rc = get_user_sid(&usersid);
894         if (rc != ERROR_SUCCESS || !usersid)
895         {
896             ERR("Failed to retrieve user SID: %d\n", rc);
897             return rc;
898         }
899 
900         sprintfW(keypath, szInstallProperties_fmt, usersid, squished_pc);
901         LocalFree(usersid);
902     }
903 
904     if (create)
905         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
906 
907     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
908 }
909 
910 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
911 {
912     UINT rc;
913     WCHAR squished_pc[GUID_SIZE];
914     WCHAR keypath[0x200];
915     LPWSTR usersid;
916 
917     TRACE("%s\n", debugstr_w(szProduct));
918     if (!squash_guid(szProduct, squished_pc))
919         return ERROR_FUNCTION_FAILED;
920     TRACE("squished (%s)\n", debugstr_w(squished_pc));
921 
922     rc = get_user_sid(&usersid);
923     if (rc != ERROR_SUCCESS || !usersid)
924     {
925         ERR("Failed to retrieve user SID: %d\n", rc);
926         return rc;
927     }
928 
929     sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
930 
931     LocalFree(usersid);
932     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
933 }
934 
935 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
936 {
937     WCHAR squished_pc[GUID_SIZE];
938     WCHAR keypath[0x200];
939 
940     TRACE("%s\n", debugstr_w(szProduct));
941     if (!squash_guid(szProduct, squished_pc))
942         return ERROR_FUNCTION_FAILED;
943     TRACE("squished (%s)\n", debugstr_w(squished_pc));
944 
945     sprintfW(keypath, szInstaller_Products_fmt, squished_pc);
946 
947     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
948 }
949 
950 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
951 {
952     UINT rc;
953     WCHAR squished_pc[GUID_SIZE];
954     WCHAR keypath[0x200];
955 
956     TRACE("%s\n",debugstr_w(szPatch));
957     if (!squash_guid(szPatch,squished_pc))
958         return ERROR_FUNCTION_FAILED;
959     TRACE("squished (%s)\n", debugstr_w(squished_pc));
960 
961     sprintfW(keypath,szInstaller_Patches_fmt,squished_pc);
962 
963     if (create)
964         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
965     else
966         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
967 
968     return rc;
969 }
970 
971 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
972 {
973     UINT rc;
974     WCHAR squished_pc[GUID_SIZE];
975     WCHAR keypath[0x200];
976 
977     TRACE("%s\n",debugstr_w(szUpgradeCode));
978     if (!squash_guid(szUpgradeCode,squished_pc))
979         return ERROR_FUNCTION_FAILED;
980     TRACE("squished (%s)\n", debugstr_w(squished_pc));
981 
982     sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
983 
984     if (create)
985         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
986     else
987         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
988 
989     return rc;
990 }
991 
992 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
993 {
994     UINT rc;
995     WCHAR squished_pc[GUID_SIZE];
996     WCHAR keypath[0x200];
997 
998     TRACE("%s\n",debugstr_w(szUpgradeCode));
999     if (!squash_guid(szUpgradeCode,squished_pc))
1000         return ERROR_FUNCTION_FAILED;
1001     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1002 
1003     sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1004 
1005     if (create)
1006         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
1007     else
1008         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
1009 
1010     return rc;
1011 }
1012 
1013 UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
1014 {
1015     WCHAR squished_pc[GUID_SIZE];
1016     WCHAR keypath[0x200];
1017 
1018     TRACE("%s\n",debugstr_w(szUpgradeCode));
1019     if (!squash_guid(szUpgradeCode,squished_pc))
1020         return ERROR_FUNCTION_FAILED;
1021     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1022 
1023     sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1024 
1025     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
1026 }
1027 
1028 UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
1029 {
1030     WCHAR squished_pc[GUID_SIZE];
1031     WCHAR keypath[0x200];
1032 
1033     TRACE("%s\n", debugstr_w(szProductCode));
1034 
1035     if (!squash_guid(szProductCode, squished_pc))
1036         return ERROR_FUNCTION_FAILED;
1037 
1038     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1039 
1040     sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
1041 
1042     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
1043 }
1044 
1045 UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
1046 {
1047     WCHAR squished_pc[GUID_SIZE];
1048     WCHAR keypath[0x200];
1049 
1050     TRACE("%s\n", debugstr_w(szProductCode));
1051 
1052     if (!squash_guid(szProductCode, squished_pc))
1053         return ERROR_FUNCTION_FAILED;
1054 
1055     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1056 
1057     sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
1058 
1059     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
1060 }
1061 
1062 UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
1063 {
1064     WCHAR squished_pc[GUID_SIZE];
1065     WCHAR keypath[0x200];
1066 
1067     TRACE("%s\n", debugstr_w(szUpgradeCode));
1068     if (!squash_guid(szUpgradeCode, squished_pc))
1069         return ERROR_FUNCTION_FAILED;
1070     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1071 
1072     sprintfW(keypath, szInstaller_ClassesUpgrade_fmt, squished_pc);
1073 
1074     if (create)
1075         return RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, key);
1076 
1077     return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key);
1078 }
1079 
1080 /*************************************************************************
1081  *  MsiDecomposeDescriptorW   [MSI.@]
1082  *
1083  * Decomposes an MSI descriptor into product, feature and component parts.
1084  * An MSI descriptor is a string of the form:
1085  *   [base 85 guid] [feature code] '>' [base 85 guid]
1086  *
1087  * PARAMS
1088  *   szDescriptor  [I]  the descriptor to decompose
1089  *   szProduct     [O]  buffer of MAX_FEATURE_CHARS+1 for the product guid
1090  *   szFeature     [O]  buffer of MAX_FEATURE_CHARS+1 for the feature code
1091  *   szComponent   [O]  buffer of MAX_FEATURE_CHARS+1 for the component guid
1092  *   pUsed         [O]  the length of the descriptor
1093  *
1094  * RETURNS
1095  *   ERROR_SUCCESS             if everything worked correctly
1096  *   ERROR_INVALID_PARAMETER   if the descriptor was invalid
1097  *
1098  */
1099 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
1100                 LPWSTR szFeature, LPWSTR szComponent, LPDWORD pUsed )
1101 {
1102     UINT r, len;
1103     LPWSTR p;
1104     GUID product, component;
1105 
1106     TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
1107           szFeature, szComponent, pUsed);
1108 
1109     r = decode_base85_guid( szDescriptor, &product );
1110     if( !r )
1111         return ERROR_INVALID_PARAMETER;
1112 
1113     TRACE("product %s\n", debugstr_guid( &product ));
1114 
1115     p = strchrW(&szDescriptor[20],'>');
1116     if( !p )
1117         return ERROR_INVALID_PARAMETER;
1118 
1119     len = (p - &szDescriptor[20]);
1120     if( len > MAX_FEATURE_CHARS )
1121         return ERROR_INVALID_PARAMETER;
1122 
1123     TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
1124 
1125     r = decode_base85_guid( p+1, &component );
1126     if( !r )
1127         return ERROR_INVALID_PARAMETER;
1128 
1129     TRACE("component %s\n", debugstr_guid( &component ));
1130 
1131     if (szProduct)
1132         StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
1133     if (szComponent)
1134         StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
1135     if (szFeature)
1136     {
1137         memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
1138         szFeature[len] = 0;
1139     }
1140     len = ( &p[21] - szDescriptor );
1141 
1142     TRACE("length = %d\n", len);
1143     *pUsed = len;
1144 
1145     return ERROR_SUCCESS;
1146 }
1147 
1148 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
1149                 LPSTR szFeature, LPSTR szComponent, LPDWORD pUsed )
1150 {
1151     WCHAR product[MAX_FEATURE_CHARS+1];
1152     WCHAR feature[MAX_FEATURE_CHARS+1];
1153     WCHAR component[MAX_FEATURE_CHARS+1];
1154     LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
1155     UINT r;
1156 
1157     TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
1158           szFeature, szComponent, pUsed);
1159 
1160     str = strdupAtoW( szDescriptor );
1161     if( szDescriptor && !str )
1162         return ERROR_OUTOFMEMORY;
1163 
1164     if (szProduct)
1165         p = product;
1166     if (szFeature)
1167         f = feature;
1168     if (szComponent)
1169         c = component;
1170 
1171     r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
1172 
1173     if (r == ERROR_SUCCESS)
1174     {
1175         WideCharToMultiByte( CP_ACP, 0, p, -1,
1176                              szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
1177         WideCharToMultiByte( CP_ACP, 0, f, -1,
1178                              szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
1179         WideCharToMultiByte( CP_ACP, 0, c, -1,
1180                              szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
1181     }
1182 
1183     msi_free( str );
1184 
1185     return r;
1186 }
1187 
1188 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
1189 {
1190     DWORD r;
1191     WCHAR szwGuid[GUID_SIZE];
1192 
1193     TRACE("%d %p\n", index, lpguid);
1194 
1195     if (NULL == lpguid)
1196         return ERROR_INVALID_PARAMETER;
1197     r = MsiEnumProductsW(index, szwGuid);
1198     if( r == ERROR_SUCCESS )
1199         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1200 
1201     return r;
1202 }
1203 
1204 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
1205 {
1206     HKEY hkeyProducts = 0;
1207     DWORD r;
1208     WCHAR szKeyName[SQUISH_GUID_SIZE];
1209 
1210     TRACE("%d %p\n", index, lpguid);
1211 
1212     if (NULL == lpguid)
1213         return ERROR_INVALID_PARAMETER;
1214 
1215     r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
1216     if( r != ERROR_SUCCESS )
1217         return ERROR_NO_MORE_ITEMS;
1218 
1219     r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
1220     if( r == ERROR_SUCCESS )
1221         unsquash_guid(szKeyName, lpguid);
1222     RegCloseKey(hkeyProducts);
1223 
1224     return r;
1225 }
1226 
1227 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
1228       LPSTR szFeature, LPSTR szParent)
1229 {
1230     DWORD r;
1231     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
1232     LPWSTR szwProduct = NULL;
1233 
1234     TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
1235 
1236     if( szProduct )
1237     {
1238         szwProduct = strdupAtoW( szProduct );
1239         if( !szwProduct )
1240             return ERROR_OUTOFMEMORY;
1241     }
1242 
1243     r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
1244     if( r == ERROR_SUCCESS )
1245     {
1246         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
1247                             szFeature, GUID_SIZE, NULL, NULL);
1248         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
1249                             szParent, GUID_SIZE, NULL, NULL);
1250     }
1251 
1252     msi_free( szwProduct);
1253 
1254     return r;
1255 }
1256 
1257 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
1258       LPWSTR szFeature, LPWSTR szParent)
1259 {
1260     HKEY hkeyProduct = 0;
1261     DWORD r, sz;
1262 
1263     TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
1264 
1265     if( !szProduct )
1266         return ERROR_INVALID_PARAMETER;
1267 
1268     r = MSIREG_OpenInstallerFeaturesKey(szProduct,&hkeyProduct,FALSE);
1269     if( r != ERROR_SUCCESS )
1270         return ERROR_NO_MORE_ITEMS;
1271 
1272     sz = GUID_SIZE;
1273     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1274     RegCloseKey(hkeyProduct);
1275 
1276     return r;
1277 }
1278 
1279 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1280 {
1281     DWORD r;
1282     WCHAR szwGuid[GUID_SIZE];
1283 
1284     TRACE("%d %p\n", index, lpguid);
1285 
1286     r = MsiEnumComponentsW(index, szwGuid);
1287     if( r == ERROR_SUCCESS )
1288         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1289 
1290     return r;
1291 }
1292 
1293 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1294 {
1295     HKEY hkeyComponents = 0;
1296     DWORD r;
1297     WCHAR szKeyName[SQUISH_GUID_SIZE];
1298 
1299     TRACE("%d %p\n", index, lpguid);
1300 
1301     r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Components, &hkeyComponents);
1302     if( r != ERROR_SUCCESS )
1303         return ERROR_NO_MORE_ITEMS;
1304 
1305     r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
1306     if( r == ERROR_SUCCESS )
1307         unsquash_guid(szKeyName, lpguid);
1308     RegCloseKey(hkeyComponents);
1309 
1310     return r;
1311 }
1312 
1313 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1314 {
1315     DWORD r;
1316     WCHAR szwProduct[GUID_SIZE];
1317     LPWSTR szwComponent = NULL;
1318 
1319     TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
1320 
1321     if ( !szProduct )
1322         return ERROR_INVALID_PARAMETER;
1323 
1324     if( szComponent )
1325     {
1326         szwComponent = strdupAtoW( szComponent );
1327         if( !szwComponent )
1328             return ERROR_OUTOFMEMORY;
1329     }
1330 
1331     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1332     if( r == ERROR_SUCCESS )
1333     {
1334         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1335                             szProduct, GUID_SIZE, NULL, NULL);
1336     }
1337 
1338     msi_free( szwComponent);
1339 
1340     return r;
1341 }
1342 
1343 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1344 {
1345     HKEY hkeyComp = 0;
1346     DWORD r, sz;
1347     WCHAR szValName[SQUISH_GUID_SIZE];
1348 
1349     TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
1350 
1351     if (!szComponent || !*szComponent || !szProduct)
1352         return ERROR_INVALID_PARAMETER;
1353 
1354     if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkeyComp, FALSE) != ERROR_SUCCESS &&
1355         MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkeyComp, FALSE) != ERROR_SUCCESS)
1356         return ERROR_UNKNOWN_COMPONENT;
1357 
1358     /* see if there are any products at all */
1359     sz = SQUISH_GUID_SIZE;
1360     r = RegEnumValueW(hkeyComp, 0, szValName, &sz, NULL, NULL, NULL, NULL);
1361     if (r != ERROR_SUCCESS)
1362     {
1363         RegCloseKey(hkeyComp);
1364 
1365         if (index != 0)
1366             return ERROR_INVALID_PARAMETER;
1367 
1368         return ERROR_UNKNOWN_COMPONENT;
1369     }
1370 
1371     sz = SQUISH_GUID_SIZE;
1372     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1373     if( r == ERROR_SUCCESS )
1374         unsquash_guid(szValName, szProduct);
1375 
1376     RegCloseKey(hkeyComp);
1377 
1378     return r;
1379 }
1380 
1381 static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
1382                 awstring *lpQualBuf, LPDWORD pcchQual,
1383                 awstring *lpAppBuf, LPDWORD pcchAppBuf )
1384 {
1385     DWORD name_sz, val_sz, name_max, val_max, type, ofs;
1386     LPWSTR name = NULL, val = NULL;
1387     UINT r, r2;
1388     HKEY key;
1389 
1390     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1391           lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
1392 
1393     if (!szComponent)
1394         return ERROR_INVALID_PARAMETER;
1395 
1396     r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1397     if (r != ERROR_SUCCESS)
1398         return ERROR_UNKNOWN_COMPONENT;
1399 
1400     /* figure out how big the name is we want to return */
1401     name_max = 0x10;
1402     r = ERROR_OUTOFMEMORY;
1403     name = msi_alloc( name_max * sizeof(WCHAR) );
1404     if (!name)
1405         goto end;
1406 
1407     val_max = 0x10;
1408     r = ERROR_OUTOFMEMORY;
1409     val = msi_alloc( val_max );
1410     if (!val)
1411         goto end;
1412 
1413     /* loop until we allocate enough memory */
1414     while (1)
1415     {
1416         name_sz = name_max;
1417         val_sz = val_max;
1418         r = RegEnumValueW( key, iIndex, name, &name_sz,
1419                            NULL, &type, (LPBYTE)val, &val_sz );
1420         if (r == ERROR_SUCCESS)
1421             break;
1422         if (r != ERROR_MORE_DATA)
1423             goto end;
1424  
1425         if (type != REG_MULTI_SZ)
1426         {
1427             ERR("component data has wrong type (%d)\n", type);
1428             goto end;
1429         }
1430 
1431         r = ERROR_OUTOFMEMORY;
1432         if ((name_sz+1) >= name_max)
1433         {
1434             name_max *= 2;
1435             msi_free( name );
1436             name = msi_alloc( name_max * sizeof (WCHAR) );
1437             if (!name)
1438                 goto end;
1439             continue;
1440         }
1441         if (val_sz > val_max)
1442         {
1443             val_max = val_sz + sizeof (WCHAR);
1444             msi_free( val );
1445             val = msi_alloc( val_max * sizeof (WCHAR) );
1446             if (!val)
1447                 goto end;
1448             continue;
1449         }
1450         ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
1451         goto end;
1452     }
1453 
1454     ofs = 0;
1455     r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1456     if (r != ERROR_SUCCESS)
1457         goto end;
1458 
1459     TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1460 
1461     r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
1462     r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
1463 
1464     if (r2 != ERROR_SUCCESS)
1465         r = r2;
1466 
1467 end:
1468     msi_free(val);
1469     msi_free(name);
1470     RegCloseKey(key);
1471 
1472     return r;
1473 }
1474 
1475 /*************************************************************************
1476  *  MsiEnumComponentQualifiersA [MSI.@]
1477  */
1478 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
1479                 LPSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1480                 LPSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1481 {
1482     awstring qual, appdata;
1483     LPWSTR comp;
1484     UINT r;
1485 
1486     TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
1487           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1488           pcchApplicationDataBuf);
1489 
1490     comp = strdupAtoW( szComponent );
1491     if (szComponent && !comp)
1492         return ERROR_OUTOFMEMORY;
1493 
1494     qual.unicode = FALSE;
1495     qual.str.a = lpQualifierBuf;
1496 
1497     appdata.unicode = FALSE;
1498     appdata.str.a = lpApplicationDataBuf;
1499 
1500     r = MSI_EnumComponentQualifiers( comp, iIndex,
1501               &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1502     msi_free( comp );
1503     return r;
1504 }
1505 
1506 /*************************************************************************
1507  *  MsiEnumComponentQualifiersW [MSI.@]
1508  */
1509 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
1510                 LPWSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1511                 LPWSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1512 {
1513     awstring qual, appdata;
1514 
1515     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1516           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1517           pcchApplicationDataBuf);
1518 
1519     qual.unicode = TRUE;
1520     qual.str.w = lpQualifierBuf;
1521 
1522     appdata.unicode = TRUE;
1523     appdata.str.w = lpApplicationDataBuf;
1524 
1525     return MSI_EnumComponentQualifiers( szComponent, iIndex,
1526                  &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1527 }
1528 
1529 /*************************************************************************
1530  *  MsiEnumRelatedProductsW   [MSI.@]
1531  *
1532  */
1533 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
1534                                     DWORD iProductIndex, LPWSTR lpProductBuf)
1535 {
1536     UINT r;
1537     HKEY hkey;
1538     DWORD dwSize = SQUISH_GUID_SIZE;
1539     WCHAR szKeyName[SQUISH_GUID_SIZE];
1540 
1541     TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
1542           iProductIndex, lpProductBuf);
1543 
1544     if (NULL == szUpgradeCode)
1545         return ERROR_INVALID_PARAMETER;
1546     if (NULL == lpProductBuf)
1547         return ERROR_INVALID_PARAMETER;
1548 
1549     r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1550     if (r != ERROR_SUCCESS)
1551         return ERROR_NO_MORE_ITEMS;
1552 
1553     r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1554     if( r == ERROR_SUCCESS )
1555         unsquash_guid(szKeyName, lpProductBuf);
1556     RegCloseKey(hkey);
1557 
1558     return r;
1559 }
1560 
1561 /*************************************************************************
1562  *  MsiEnumRelatedProductsA   [MSI.@]
1563  *
1564  */
1565 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
1566                                     DWORD iProductIndex, LPSTR lpProductBuf)
1567 {
1568     LPWSTR szwUpgradeCode = NULL;
1569     WCHAR productW[GUID_SIZE];
1570     UINT r;
1571 
1572     TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
1573           iProductIndex, lpProductBuf);
1574 
1575     if (szUpgradeCode)
1576     {
1577         szwUpgradeCode = strdupAtoW( szUpgradeCode );
1578         if( !szwUpgradeCode )
1579             return ERROR_OUTOFMEMORY;
1580     }
1581 
1582     r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1583                                  iProductIndex, productW );
1584     if (r == ERROR_SUCCESS)
1585     {
1586         WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1587                              lpProductBuf, GUID_SIZE, NULL, NULL );
1588     }
1589     msi_free( szwUpgradeCode);
1590     return r;
1591 }
1592 
1593 /***********************************************************************
1594  * MsiEnumPatchesExA            [MSI.@]
1595  */
1596 UINT WINAPI MsiEnumPatchesExA(LPCSTR szProductCode, LPCSTR szUserSid,
1597         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPSTR szPatchCode,
1598         LPSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
1599         LPSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
1600 {
1601     LPWSTR prodcode = NULL;
1602     LPWSTR usersid = NULL;
1603     LPWSTR targsid = NULL;
1604     WCHAR patch[GUID_SIZE];
1605     WCHAR targprod[GUID_SIZE];
1606     DWORD len;
1607     UINT r;
1608 
1609     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
1610           debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, dwFilter,
1611           dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
1612           szTargetUserSid, pcchTargetUserSid);
1613 
1614     if (szTargetUserSid && !pcchTargetUserSid)
1615         return ERROR_INVALID_PARAMETER;
1616 
1617     if (szProductCode) prodcode = strdupAtoW(szProductCode);
1618     if (szUserSid) usersid = strdupAtoW(szUserSid);
1619 
1620     r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1621                           patch, targprod, pdwTargetProductContext,
1622                           NULL, &len);
1623     if (r != ERROR_SUCCESS)
1624         goto done;
1625 
1626     WideCharToMultiByte(CP_ACP, 0, patch, -1, szPatchCode,
1627                         GUID_SIZE, NULL, NULL);
1628     WideCharToMultiByte(CP_ACP, 0, targprod, -1, szTargetProductCode,
1629                         GUID_SIZE, NULL, NULL);
1630 
1631     if (!szTargetUserSid)
1632     {
1633         if (pcchTargetUserSid)
1634             *pcchTargetUserSid = len;
1635 
1636         goto done;
1637     }
1638 
1639     targsid = msi_alloc(++len * sizeof(WCHAR));
1640     if (!targsid)
1641     {
1642         r = ERROR_OUTOFMEMORY;
1643         goto done;
1644     }
1645 
1646     r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1647                           patch, targprod, pdwTargetProductContext,
1648                           targsid, &len);
1649     if (r != ERROR_SUCCESS || !szTargetUserSid)
1650         goto done;
1651 
1652     WideCharToMultiByte(CP_ACP, 0, targsid, -1, szTargetUserSid,
1653                         *pcchTargetUserSid, NULL, NULL);
1654 
1655     len = lstrlenW(targsid);
1656     if (*pcchTargetUserSid < len + 1)
1657     {
1658         r = ERROR_MORE_DATA;
1659         *pcchTargetUserSid = len * sizeof(WCHAR);
1660     }
1661     else
1662         *pcchTargetUserSid = len;
1663 
1664 done:
1665     msi_free(prodcode);
1666     msi_free(usersid);
1667     msi_free(targsid);
1668 
1669     return r;
1670 }
1671 
1672 static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
1673                                 LPWSTR patch, MSIPATCHSTATE *state)
1674 {
1675     DWORD type, val, size;
1676     HKEY prod, hkey = 0;
1677     HKEY udpatch = 0;
1678     LONG res;
1679     UINT r = ERROR_NO_MORE_ITEMS;
1680 
1681     static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1682     static const WCHAR szState[] = {'S','t','a','t','e',0};
1683 
1684     *state = MSIPATCHSTATE_INVALID;
1685 
1686     /* FIXME: usersid might not be current user */
1687     r = MSIREG_OpenUserDataProductKey(prodcode, MSIINSTALLCONTEXT_USERUNMANAGED,
1688                                       NULL, &prod, FALSE);
1689     if (r != ERROR_SUCCESS)
1690         return ERROR_NO_MORE_ITEMS;
1691 
1692     res = RegOpenKeyExW(prod, szPatches, 0, KEY_READ, &hkey);
1693     if (res != ERROR_SUCCESS)
1694         goto done;
1695 
1696     res = RegOpenKeyExW(hkey, patch, 0, KEY_READ, &udpatch);
1697     if (res != ERROR_SUCCESS)
1698         goto done;
1699 
1700     size = sizeof(DWORD);
1701     res = RegGetValueW(udpatch, NULL, szState, RRF_RT_DWORD, &type, &val, &size);
1702     if (res != ERROR_SUCCESS ||
1703         val < MSIPATCHSTATE_APPLIED || val > MSIPATCHSTATE_REGISTERED)
1704     {
1705         r = ERROR_BAD_CONFIGURATION;
1706         goto done;
1707     }
1708 
1709     *state = val;
1710     r = ERROR_SUCCESS;
1711 
1712 done:
1713     RegCloseKey(udpatch);
1714     RegCloseKey(hkey);
1715     RegCloseKey(prod);
1716 
1717     return r;
1718 }
1719 
1720 static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
1721         MSIINSTALLCONTEXT context, DWORD filter, DWORD index, DWORD *idx,
1722         LPWSTR patch, LPWSTR targetprod, MSIINSTALLCONTEXT *targetctx,
1723         LPWSTR targetsid, DWORD *sidsize, LPWSTR *transforms)
1724 {
1725     MSIPATCHSTATE state;
1726     LPWSTR ptr, patches = NULL;
1727     HKEY prod, patchkey = 0;
1728     HKEY localprod = 0, localpatch = 0;
1729     DWORD type, size;
1730     LONG res;
1731     UINT temp, r = ERROR_NO_MORE_ITEMS;
1732 
1733     static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1734     static const WCHAR szState[] = {'S','t','a','t','e',0};
1735     static const WCHAR szEmpty[] = {0};
1736 
1737     if (MSIREG_OpenProductKey(prodcode, context, &prod, FALSE) != ERROR_SUCCESS)
1738         return ERROR_NO_MORE_ITEMS;
1739 
1740     size = 0;
1741     res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type, NULL,
1742                        &size);
1743     if (res != ERROR_SUCCESS)
1744         goto done;
1745 
1746     if (type != REG_MULTI_SZ)
1747     {
1748         r = ERROR_BAD_CONFIGURATION;
1749         goto done;
1750     }
1751 
1752     patches = msi_alloc(size);
1753     if (!patches)
1754     {
1755         r = ERROR_OUTOFMEMORY;
1756         goto done;
1757     }
1758 
1759     res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type,
1760                        patches, &size);
1761     if (res != ERROR_SUCCESS)
1762         goto done;
1763 
1764     ptr = patches;
1765     for (ptr = patches; *ptr && r == ERROR_NO_MORE_ITEMS; ptr += lstrlenW(ptr))
1766     {
1767         if (!unsquash_guid(ptr, patch))
1768         {
1769             r = ERROR_BAD_CONFIGURATION;
1770             goto done;
1771         }
1772 
1773         size = 0;
1774         res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
1775                            &type, NULL, &size);
1776         if (res != ERROR_SUCCESS)
1777             continue;
1778 
1779         if (transforms)
1780         {
1781             *transforms = msi_alloc(size);
1782             if (!*transforms)
1783             {
1784                 r = ERROR_OUTOFMEMORY;
1785                 goto done;
1786             }
1787 
1788             res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
1789                                &type, *transforms, &size);
1790             if (res != ERROR_SUCCESS)
1791                 continue;
1792         }
1793 
1794         if (context == MSIINSTALLCONTEXT_USERMANAGED)
1795         {
1796             if (!(filter & MSIPATCHSTATE_APPLIED))
1797             {
1798                 temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
1799                 if (temp == ERROR_BAD_CONFIGURATION)
1800                 {
1801                     r = ERROR_BAD_CONFIGURATION;
1802                     goto done;
1803                 }
1804 
1805                 if (temp != ERROR_SUCCESS || !(filter & state))
1806                     continue;
1807             }
1808         }
1809         else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
1810         {
1811             if (!(filter & MSIPATCHSTATE_APPLIED))
1812             {
1813                 temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
1814                 if (temp == ERROR_BAD_CONFIGURATION)
1815                 {
1816                     r = ERROR_BAD_CONFIGURATION;
1817                     goto done;
1818                 }
1819 
1820                 if (temp != ERROR_SUCCESS || !(filter & state))
1821                     continue;
1822             }
1823             else
1824             {
1825                 temp = MSIREG_OpenUserDataPatchKey(patch, context,
1826                                                    &patchkey, FALSE);
1827                 RegCloseKey(patchkey);
1828                 if (temp != ERROR_SUCCESS)
1829                     continue;
1830             }
1831         }
1832         else if (context == MSIINSTALLCONTEXT_MACHINE)
1833         {
1834             usersid = szEmpty;
1835 
1836             if (MSIREG_OpenUserDataProductKey(prodcode, context, NULL, &localprod, FALSE) == ERROR_SUCCESS &&
1837                 RegOpenKeyExW(localprod, szPatches, 0, KEY_READ, &localpatch) == ERROR_SUCCESS &&
1838                 RegOpenKeyExW(localpatch, ptr, 0, KEY_READ, &patchkey) == ERROR_SUCCESS)
1839             {
1840                 res = RegGetValueW(patchkey, NULL, szState, RRF_RT_REG_DWORD,
1841                                    &type, &state, &size);
1842 
1843                 if (!(filter & state))
1844                     res = ERROR_NO_MORE_ITEMS;
1845 
1846                 RegCloseKey(patchkey);
1847             }
1848 
1849             RegCloseKey(localpatch);
1850             RegCloseKey(localprod);
1851 
1852             if (res != ERROR_SUCCESS)
1853                 continue;
1854         }
1855 
1856         if (*idx < index)
1857         {
1858             (*idx)++;
1859             continue;
1860         }
1861 
1862         r = ERROR_SUCCESS;
1863         if (targetprod)
1864             lstrcpyW(targetprod, prodcode);
1865 
1866         if (targetctx)
1867             *targetctx = context;
1868 
1869         if (targetsid)
1870         {
1871             lstrcpynW(targetsid, usersid, *sidsize);
1872             if (lstrlenW(usersid) >= *sidsize)
1873                 r = ERROR_MORE_DATA;
1874         }
1875 
1876         if (sidsize)
1877         {
1878             *sidsize = lstrlenW(usersid);
1879             if (!targetsid)
1880                 *sidsize *= sizeof(WCHAR);
1881         }
1882     }
1883 
1884 done:
1885     RegCloseKey(prod);
1886     msi_free(patches);
1887 
1888     return r;
1889 }
1890 
1891 static UINT msi_enum_patches(LPCWSTR szProductCode, LPCWSTR szUserSid,
1892         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, DWORD *idx,
1893         LPWSTR szPatchCode, LPWSTR szTargetProductCode,
1894         MSIINSTALLCONTEXT *pdwTargetProductContext, LPWSTR szTargetUserSid,
1895         LPDWORD pcchTargetUserSid, LPWSTR *szTransforms)
1896 {
1897     UINT r;
1898 
1899     if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
1900     {
1901         r = msi_check_product_patches(szProductCode, szUserSid,
1902                                       MSIINSTALLCONTEXT_USERMANAGED, dwFilter,
1903                                       dwIndex, idx, szPatchCode,
1904                                       szTargetProductCode,
1905                                       pdwTargetProductContext, szTargetUserSid,
1906                                       pcchTargetUserSid, szTransforms);
1907         if (r != ERROR_NO_MORE_ITEMS)
1908             goto done;
1909     }
1910 
1911     if (dwContext & MSIINSTALLCONTEXT_USERUNMANAGED)
1912     {
1913         r = msi_check_product_patches(szProductCode, szUserSid,
1914                                       MSIINSTALLCONTEXT_USERUNMANAGED, dwFilter,
1915                                       dwIndex, idx, szPatchCode,
1916                                       szTargetProductCode,
1917                                       pdwTargetProductContext, szTargetUserSid,
1918                                       pcchTargetUserSid, szTransforms);
1919         if (r != ERROR_NO_MORE_ITEMS)
1920             goto done;
1921     }
1922 
1923     if (dwContext & MSIINSTALLCONTEXT_MACHINE)
1924     {
1925         r = msi_check_product_patches(szProductCode, szUserSid,
1926                                       MSIINSTALLCONTEXT_MACHINE, dwFilter,
1927                                       dwIndex, idx, szPatchCode,
1928                                       szTargetProductCode,
1929                                       pdwTargetProductContext, szTargetUserSid,
1930                                       pcchTargetUserSid, szTransforms);
1931         if (r != ERROR_NO_MORE_ITEMS)
1932             goto done;
1933     }
1934 
1935 done:
1936     return r;
1937 }
1938 
1939 /***********************************************************************
1940  * MsiEnumPatchesExW            [MSI.@]
1941  */
1942 UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1943         DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPWSTR szPatchCode,
1944         LPWSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
1945         LPWSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
1946 {
1947     WCHAR squished_pc[GUID_SIZE];
1948     DWORD idx = 0;
1949     UINT r;
1950 
1951     static int last_index = 0;
1952 
1953     TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
1954           debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter,
1955           dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
1956           szTargetUserSid, pcchTargetUserSid);
1957 
1958     if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1959         return ERROR_INVALID_PARAMETER;
1960 
1961     if (!lstrcmpW(szUserSid, szLocalSid))
1962         return ERROR_INVALID_PARAMETER;
1963 
1964     if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
1965         return ERROR_INVALID_PARAMETER;
1966 
1967     if (dwContext <= MSIINSTALLCONTEXT_NONE ||
1968         dwContext > MSIINSTALLCONTEXT_ALL)
1969         return ERROR_INVALID_PARAMETER;
1970 
1971     if (dwFilter <= MSIPATCHSTATE_INVALID || dwFilter > MSIPATCHSTATE_ALL)
1972         return ERROR_INVALID_PARAMETER;
1973 
1974     if (dwIndex && dwIndex - last_index != 1)
1975         return ERROR_INVALID_PARAMETER;
1976 
1977     if (dwIndex == 0)
1978         last_index = 0;
1979 
1980     r = msi_enum_patches(szProductCode, szUserSid, dwContext, dwFilter,
1981                          dwIndex, &idx, szPatchCode, szTargetProductCode,
1982                          pdwTargetProductContext, szTargetUserSid,
1983                          pcchTargetUserSid, NULL);
1984 
1985     if (r == ERROR_SUCCESS)
1986         last_index = dwIndex;
1987 
1988     return r;
1989 }
1990 
1991 /***********************************************************************
1992  * MsiEnumPatchesA            [MSI.@]
1993  */
1994 UINT WINAPI MsiEnumPatchesA(LPCSTR szProduct, DWORD iPatchIndex,
1995         LPSTR lpPatchBuf, LPSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
1996 {
1997     LPWSTR product, transforms = NULL;
1998     WCHAR patch[GUID_SIZE];
1999     DWORD len;
2000     UINT r;
2001 
2002     TRACE("(%s %d %p %p %p)\n", debugstr_a(szProduct), iPatchIndex,
2003           lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
2004 
2005     if (!szProduct || !lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
2006         return ERROR_INVALID_PARAMETER;
2007 
2008     product = strdupAtoW(szProduct);
2009     if (!product)
2010         return ERROR_OUTOFMEMORY;
2011 
2012     len = 0;
2013     r = MsiEnumPatchesW(product, iPatchIndex, patch, patch, &len);
2014     if (r != ERROR_MORE_DATA)
2015         goto done;
2016 
2017     transforms = msi_alloc(len);
2018     if (!transforms)
2019     {
2020         r = ERROR_OUTOFMEMORY;
2021         goto done;
2022     }
2023 
2024     r = MsiEnumPatchesW(product, iPatchIndex, patch, transforms, &len);
2025     if (r != ERROR_SUCCESS)
2026         goto done;
2027 
2028     WideCharToMultiByte(CP_ACP, 0, patch, -1, lpPatchBuf,
2029                         GUID_SIZE, NULL, NULL);
2030 
2031     WideCharToMultiByte(CP_ACP, 0, transforms, -1, lpTransformsBuf,
2032                         *pcchTransformsBuf - 1, NULL, NULL);
2033 
2034     len = lstrlenW(transforms);
2035     if (*pcchTransformsBuf < len + 1)
2036     {
2037         r = ERROR_MORE_DATA;
2038         lpTransformsBuf[*pcchTransformsBuf - 1] = '\0';
2039         *pcchTransformsBuf = len * sizeof(WCHAR);
2040     }
2041     else
2042         *pcchTransformsBuf = len;
2043 
2044 done:
2045     msi_free(transforms);
2046     msi_free(product);
2047 
2048     return r;
2049 }
2050 
2051 /***********************************************************************
2052  * MsiEnumPatchesW            [MSI.@]
2053  */
2054 UINT WINAPI MsiEnumPatchesW(LPCWSTR szProduct, DWORD iPatchIndex,
2055         LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
2056 {
2057     WCHAR squished_pc[GUID_SIZE];
2058     LPWSTR transforms = NULL;
2059     HKEY prod;
2060     DWORD idx = 0;
2061     UINT r;
2062 
2063     TRACE("(%s %d %p %p %p)\n", debugstr_w(szProduct), iPatchIndex,
2064           lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
2065 
2066     if (!szProduct || !squash_guid(szProduct, squished_pc))
2067         return ERROR_INVALID_PARAMETER;
2068 
2069     if (!lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
2070         return ERROR_INVALID_PARAMETER;
2071 
2072     if (MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERMANAGED,
2073                               &prod, FALSE) != ERROR_SUCCESS &&
2074         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED,
2075                               &prod, FALSE) != ERROR_SUCCESS &&
2076         MSIREG_OpenProductKey(szProduct, MSIINSTALLCONTEXT_MACHINE,
2077                               &prod, FALSE) != ERROR_SUCCESS)
2078         return ERROR_UNKNOWN_PRODUCT;
2079 
2080     RegCloseKey(prod);
2081 
2082     r = msi_enum_patches(szProduct, NULL, MSIINSTALLCONTEXT_ALL,
2083                          MSIPATCHSTATE_ALL, iPatchIndex, &idx, lpPatchBuf,
2084                          NULL, NULL, NULL, NULL, &transforms);
2085     if (r != ERROR_SUCCESS)
2086         goto done;
2087 
2088     lstrcpynW(lpTransformsBuf, transforms, *pcchTransformsBuf);
2089     if (*pcchTransformsBuf <= lstrlenW(transforms))
2090     {
2091         r = ERROR_MORE_DATA;
2092         *pcchTransformsBuf = lstrlenW(transforms) * sizeof(WCHAR);
2093     }
2094     else
2095         *pcchTransformsBuf = lstrlenW(transforms);
2096 
2097 done:
2098     msi_free(transforms);
2099     return r;
2100 }
2101 
2102 UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
2103         DWORD dwContext, DWORD dwIndex, CHAR szInstalledProductCode[39],
2104         MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
2105 {
2106     FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
2107           dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
2108           szSid, pcchSid);
2109     return ERROR_NO_MORE_ITEMS;
2110 }
2111 
2112 UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
2113         DWORD dwContext, DWORD dwIndex, WCHAR szInstalledProductCode[39],
2114         MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
2115 {
2116     FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
2117           dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
2118           szSid, pcchSid);
2119     return ERROR_NO_MORE_ITEMS;
2120 }
2121 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.