~ [ 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 szInstallProperties_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','r','o','d','u','c','t','s','\\','%','s','\\',
179 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
180 
181 static const WCHAR szInstaller_LocalSystemProductCodes_fmt[] = {
182 'S','o','f','t','w','a','r','e','\\',
183 'M','i','c','r','o','s','o','f','t','\\',
184 'W','i','n','d','o','w','s','\\',
185 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
186 'I','n','s','t','a','l','l','e','r','\\',
187 'U','s','e','r','D','a','t','a','\\',
188 'S','-','1','-','5','-','1','8','\\','P','r','o','d','u','c','t','s','\\',
189 '%','s','\\','I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
190 
191 static const WCHAR szInstaller_LocalSystemComponent_fmt[] = {
192 'S','o','f','t','w','a','r','e','\\',
193 'M','i','c','r','o','s','o','f','t','\\',
194 'W','i','n','d','o','w','s','\\',
195 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
196 'I','n','s','t','a','l','l','e','r','\\',
197 'U','s','e','r','D','a','t','a','\\',
198 'S','-','1','-','5','-','1','8','\\',
199 'C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
200 
201 static const WCHAR szInstaller_LocalClassesProd_fmt[] = {
202 'S','o','f','t','w','a','r','e','\\',
203 'C','l','a','s','s','e','s','\\',
204 'I','n','s','t','a','l','l','e','r','\\',
205 'P','r','o','d','u','c','t','s','\\','%','s',0};
206 
207 static const WCHAR szInstaller_LocalClassesFeat_fmt[] = {
208 'S','o','f','t','w','a','r','e','\\',
209 'C','l','a','s','s','e','s','\\',
210 'I','n','s','t','a','l','l','e','r','\\',
211 'F','e','a','t','u','r','e','s','\\','%','s',0};
212 
213 static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
214 'S','o','f','t','w','a','r','e','\\',
215 'M','i','c','r','o','s','o','f','t','\\',
216 'W','i','n','d','o','w','s','\\',
217 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
218 'I','n','s','t','a','l','l','e','r','\\',
219 'M','a','n','a','g','e','d','\\','%','s','\\',
220 'I','n','s','t','a','l','l','e','r','\\',
221 'P','r','o','d','u','c','t','s','\\','%','s',0};
222 
223 static const WCHAR szInstaller_LocalManagedFeat_fmt[] = {
224 'S','o','f','t','w','a','r','e','\\',
225 'M','i','c','r','o','s','o','f','t','\\',
226 'W','i','n','d','o','w','s','\\',
227 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
228 'I','n','s','t','a','l','l','e','r','\\',
229 'M','a','n','a','g','e','d','\\','%','s','\\',
230 'I','n','s','t','a','l','l','e','r','\\',
231 'F','e','a','t','u','r','e','s','\\','%','s',0};
232 
233 static const WCHAR szInstaller_ClassesUpgrade_fmt[] = {
234 'I','n','s','t','a','l','l','e','r','\\',
235 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
236 '%','s',0};
237 
238 static const WCHAR localsid[] = {'S','-','1','-','5','-','1','8',0};
239 
240 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
241 {
242     DWORD i,n=0;
243 
244     out[n++]='{';
245     for(i=0; i<8; i++)
246         out[n++] = in[7-i];
247     out[n++]='-';
248     for(i=0; i<4; i++)
249         out[n++] = in[11-i];
250     out[n++]='-';
251     for(i=0; i<4; i++)
252         out[n++] = in[15-i];
253     out[n++]='-';
254     for(i=0; i<2; i++)
255     {
256         out[n++] = in[17+i*2];
257         out[n++] = in[16+i*2];
258     }
259     out[n++]='-';
260     for( ; i<8; i++)
261     {
262         out[n++] = in[17+i*2];
263         out[n++] = in[16+i*2];
264     }
265     out[n++]='}';
266     out[n]=0;
267     return TRUE;
268 }
269 
270 BOOL squash_guid(LPCWSTR in, LPWSTR out)
271 {
272     DWORD i,n=1;
273     GUID guid;
274 
275     out[0] = 0;
276 
277     if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
278         return FALSE;
279 
280     for(i=0; i<8; i++)
281         out[7-i] = in[n++];
282     n++;
283     for(i=0; i<4; i++)
284         out[11-i] = in[n++];
285     n++;
286     for(i=0; i<4; i++)
287         out[15-i] = in[n++];
288     n++;
289     for(i=0; i<2; i++)
290     {
291         out[17+i*2] = in[n++];
292         out[16+i*2] = in[n++];
293     }
294     n++;
295     for( ; i<8; i++)
296     {
297         out[17+i*2] = in[n++];
298         out[16+i*2] = in[n++];
299     }
300     out[32]=0;
301     return TRUE;
302 }
303 
304 
305 /* tables for encoding and decoding base85 */
306 static const unsigned char table_dec85[0x80] = {
307 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
308 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
309 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
310 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
311 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
312 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
313 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
314 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
315 };
316 
317 static const char table_enc85[] =
318 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
319 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
320 "yz{}~";
321 
322 /*
323  *  Converts a base85 encoded guid into a GUID pointer
324  *  Base85 encoded GUIDs should be 20 characters long.
325  *
326  *  returns TRUE if successful, FALSE if not
327  */
328 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
329 {
330     DWORD i, val = 0, base = 1, *p;
331 
332     if (!str)
333         return FALSE;
334 
335     p = (DWORD*) guid;
336     for( i=0; i<20; i++ )
337     {
338         if( (i%5) == 0 )
339         {
340             val = 0;
341             base = 1;
342         }
343         val += table_dec85[str[i]] * base;
344         if( str[i] >= 0x80 )
345             return FALSE;
346         if( table_dec85[str[i]] == 0xff )
347             return FALSE;
348         if( (i%5) == 4 )
349             p[i/5] = val;
350         base *= 85;
351     }
352     return TRUE;
353 }
354 
355 /*
356  *  Encodes a base85 guid given a GUID pointer
357  *  Caller should provide a 21 character buffer for the encoded string.
358  *
359  *  returns TRUE if successful, FALSE if not
360  */
361 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
362 {
363     unsigned int x, *p, i;
364 
365     p = (unsigned int*) guid;
366     for( i=0; i<4; i++ )
367     {
368         x = p[i];
369         *str++ = table_enc85[x%85];
370         x = x/85;
371         *str++ = table_enc85[x%85];
372         x = x/85;
373         *str++ = table_enc85[x%85];
374         x = x/85;
375         *str++ = table_enc85[x%85];
376         x = x/85;
377         *str++ = table_enc85[x%85];
378     }
379     *str = 0;
380 
381     return TRUE;
382 }
383 
384 DWORD msi_version_str_to_dword(LPCWSTR p)
385 {
386     DWORD major, minor = 0, build = 0, version = 0;
387 
388     if (!p)
389         return version;
390 
391     major = atoiW(p);
392 
393     p = strchrW(p, '.');
394     if (p)
395     {
396         minor = atoiW(p+1);
397         p = strchrW(p+1, '.');
398         if (p)
399             build = atoiW(p+1);
400     }
401 
402     return MAKELONG(build, MAKEWORD(minor, major));
403 }
404 
405 LPWSTR msi_version_dword_to_str(DWORD version)
406 {
407     static const WCHAR fmt[] = { '%','u','.','%','u','.','%','u',0 };
408     LPWSTR str = msi_alloc(20);
409     sprintfW(str, fmt,
410              (version&0xff000000)>>24,
411              (version&0x00ff0000)>>16,
412               version&0x0000ffff);
413     return str;
414 }
415 
416 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
417 {
418     static const WCHAR emptyW[] = {0};
419     DWORD len;
420     if (!value) value = emptyW;
421     len = (lstrlenW(value) + 1) * sizeof (WCHAR);
422     return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
423 }
424 
425 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
426 {
427     LPCWSTR p = value;
428     while (*p) p += lstrlenW(p) + 1;
429     return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
430                            (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
431 }
432 
433 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
434 {
435     return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
436 }
437 
438 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
439 {
440     HKEY hsubkey = 0;
441     LONG r;
442 
443     r = RegCreateKeyW( hkey, path, &hsubkey );
444     if (r != ERROR_SUCCESS)
445         return r;
446     r = msi_reg_set_val_str( hsubkey, name, val );
447     RegCloseKey( hsubkey );
448     return r;
449 }
450 
451 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
452 {
453     DWORD len = 0;
454     LPWSTR val;
455     LONG r;
456 
457     r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
458     if (r != ERROR_SUCCESS)
459         return NULL;
460 
461     len += sizeof (WCHAR);
462     val = msi_alloc( len );
463     if (!val)
464         return NULL;
465     val[0] = 0;
466     RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
467     return val;
468 }
469 
470 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
471 {
472     DWORD type, len = sizeof (DWORD);
473     LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
474     return r == ERROR_SUCCESS && type == REG_DWORD;
475 }
476 
477 static UINT get_user_sid(LPWSTR *usersid)
478 {
479     HANDLE token;
480     BYTE buf[1024];
481     DWORD size;
482     PTOKEN_USER user;
483 
484     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
485         return ERROR_FUNCTION_FAILED;
486 
487     size = sizeof(buf);
488     if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size)) {
489         CloseHandle(token);
490         return ERROR_FUNCTION_FAILED;
491     }
492 
493     user = (PTOKEN_USER)buf;
494     if (!ConvertSidToStringSidW(user->User.Sid, usersid)) {
495         CloseHandle(token);
496         return ERROR_FUNCTION_FAILED;
497     }
498     CloseHandle(token);
499     return ERROR_SUCCESS;
500 }
501 
502 UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
503 {
504     UINT rc;
505     WCHAR keypath[0x200];
506     TRACE("%s\n",debugstr_w(szProduct));
507 
508     sprintfW(keypath,szUninstall_fmt,szProduct);
509 
510     if (create)
511         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
512     else
513         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
514 
515     return rc;
516 }
517 
518 UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct)
519 {
520     WCHAR keypath[0x200];
521     TRACE("%s\n",debugstr_w(szProduct));
522 
523     sprintfW(keypath,szUninstall_fmt,szProduct);
524 
525     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
526 }
527 
528 UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
529 {
530     UINT rc;
531     WCHAR squished_pc[GUID_SIZE];
532     WCHAR keypath[0x200];
533 
534     TRACE("%s\n",debugstr_w(szProduct));
535     if (!squash_guid(szProduct,squished_pc))
536         return ERROR_FUNCTION_FAILED;
537     TRACE("squished (%s)\n", debugstr_w(squished_pc));
538 
539     sprintfW(keypath,szUserProduct_fmt,squished_pc);
540 
541     if (create)
542         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
543     else
544         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
545 
546     return rc;
547 }
548 
549 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
550 {
551     WCHAR squished_pc[GUID_SIZE];
552     WCHAR keypath[0x200];
553 
554     TRACE("%s\n",debugstr_w(szProduct));
555     if (!squash_guid(szProduct,squished_pc))
556         return ERROR_FUNCTION_FAILED;
557     TRACE("squished (%s)\n", debugstr_w(squished_pc));
558 
559     sprintfW(keypath,szUserProduct_fmt,squished_pc);
560 
561     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
562 }
563 
564 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
565 {
566     UINT rc;
567     WCHAR squished_pc[GUID_SIZE];
568     WCHAR keypath[0x200];
569 
570     TRACE("%s\n",debugstr_w(szPatch));
571     if (!squash_guid(szPatch,squished_pc))
572         return ERROR_FUNCTION_FAILED;
573     TRACE("squished (%s)\n", debugstr_w(squished_pc));
574 
575     sprintfW(keypath,szUserPatch_fmt,squished_pc);
576 
577     if (create)
578         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
579     else
580         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
581 
582     return rc;
583 }
584 
585 UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
586 {
587     UINT rc;
588     WCHAR squished_pc[GUID_SIZE];
589     WCHAR keypath[0x200];
590 
591     TRACE("%s\n",debugstr_w(szProduct));
592     if (!squash_guid(szProduct,squished_pc))
593         return ERROR_FUNCTION_FAILED;
594     TRACE("squished (%s)\n", debugstr_w(squished_pc));
595 
596     sprintfW(keypath,szUserFeatures_fmt,squished_pc);
597 
598     if (create)
599         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
600     else
601         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
602 
603     return rc;
604 }
605 
606 UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
607 {
608     WCHAR squished_pc[GUID_SIZE];
609     WCHAR keypath[0x200];
610 
611     TRACE("%s\n",debugstr_w(szProduct));
612     if (!squash_guid(szProduct,squished_pc))
613         return ERROR_FUNCTION_FAILED;
614     TRACE("squished (%s)\n", debugstr_w(squished_pc));
615 
616     sprintfW(keypath,szUserFeatures_fmt,squished_pc);
617     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
618 }
619 
620 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
621 {
622     UINT rc;
623     WCHAR squished_pc[GUID_SIZE];
624     WCHAR keypath[0x200];
625 
626     TRACE("%s\n",debugstr_w(szProduct));
627     if (!squash_guid(szProduct,squished_pc))
628         return ERROR_FUNCTION_FAILED;
629     TRACE("squished (%s)\n", debugstr_w(squished_pc));
630 
631     sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
632 
633     if (create)
634         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
635     else
636         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
637 
638     return rc;
639 }
640 
641 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
642 {
643     UINT rc;
644     WCHAR squished_pc[GUID_SIZE];
645     WCHAR keypath[0x200];
646     LPWSTR usersid;
647 
648     TRACE("%s\n", debugstr_w(szProduct));
649     if (!squash_guid(szProduct, squished_pc))
650         return ERROR_FUNCTION_FAILED;
651     TRACE("squished (%s)\n", debugstr_w(squished_pc));
652 
653     rc = get_user_sid(&usersid);
654     if (rc != ERROR_SUCCESS || !usersid)
655     {
656         ERR("Failed to retrieve user SID: %d\n", rc);
657         return rc;
658     }
659 
660     sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
661 
662     if (create)
663         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
664     else
665         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
666 
667     LocalFree(usersid);
668     return rc;
669 }
670 
671 UINT MSIREG_OpenLocalUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
672 {
673     WCHAR squished_pc[GUID_SIZE];
674     WCHAR keypath[0x200];
675 
676     TRACE("%s\n", debugstr_w(szProduct));
677     if (!squash_guid(szProduct, squished_pc))
678         return ERROR_FUNCTION_FAILED;
679     TRACE("squished (%s)\n", debugstr_w(squished_pc));
680 
681     sprintfW(keypath, szUserDataFeatures_fmt, localsid, squished_pc);
682 
683     if (create)
684         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
685 
686     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
687 }
688 
689 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
690 {
691     UINT rc;
692     WCHAR squished_cc[GUID_SIZE];
693     WCHAR keypath[0x200];
694 
695     TRACE("%s\n",debugstr_w(szComponent));
696     if (!squash_guid(szComponent,squished_cc))
697         return ERROR_FUNCTION_FAILED;
698     TRACE("squished (%s)\n", debugstr_w(squished_cc));
699 
700     sprintfW(keypath,szUser_Components_fmt,squished_cc);
701 
702     if (create)
703         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
704     else
705         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
706 
707     return rc;
708 }
709 
710 UINT MSIREG_OpenLocalUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
711 {
712     WCHAR comp[GUID_SIZE];
713     WCHAR keypath[0x200];
714 
715     TRACE("%s\n", debugstr_w(szComponent));
716     if (!squash_guid(szComponent, comp))
717         return ERROR_FUNCTION_FAILED;
718     TRACE("squished (%s)\n", debugstr_w(comp));
719 
720     sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
721 
722     if (create)
723         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
724 
725     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
726 }
727 
728 UINT MSIREG_DeleteLocalUserDataComponentKey(LPCWSTR szComponent)
729 {
730     WCHAR comp[GUID_SIZE];
731     WCHAR keypath[0x200];
732 
733     TRACE("%s\n", debugstr_w(szComponent));
734     if (!squash_guid(szComponent, comp))
735         return ERROR_FUNCTION_FAILED;
736     TRACE("squished (%s)\n", debugstr_w(comp));
737 
738     sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
739     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
740 }
741 
742 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
743 {
744     UINT rc;
745     WCHAR comp[GUID_SIZE];
746     WCHAR keypath[0x200];
747     LPWSTR usersid;
748 
749     TRACE("%s\n", debugstr_w(szComponent));
750     if (!squash_guid(szComponent, comp))
751         return ERROR_FUNCTION_FAILED;
752     TRACE("squished (%s)\n", debugstr_w(comp));
753 
754     rc = get_user_sid(&usersid);
755     if (rc != ERROR_SUCCESS || !usersid)
756     {
757         ERR("Failed to retrieve user SID: %d\n", rc);
758         return rc;
759     }
760 
761     sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
762 
763     if (create)
764         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
765     else
766         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
767 
768     LocalFree(usersid);
769     return rc;
770 }
771 
772 UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent)
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     rc = get_user_sid(&usersid);
785     if (rc != ERROR_SUCCESS || !usersid)
786     {
787         ERR("Failed to retrieve user SID: %d\n", rc);
788         return rc;
789     }
790 
791     sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
792 
793     LocalFree(usersid);
794     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
795 }
796 
797 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
798 {
799     UINT rc;
800     WCHAR squished_pc[GUID_SIZE];
801     WCHAR keypath[0x200];
802     LPWSTR usersid;
803 
804     TRACE("%s\n", debugstr_w(szProduct));
805     if (!squash_guid(szProduct, squished_pc))
806         return ERROR_FUNCTION_FAILED;
807     TRACE("squished (%s)\n", debugstr_w(squished_pc));
808 
809     rc = get_user_sid(&usersid);
810     if (rc != ERROR_SUCCESS || !usersid)
811     {
812         ERR("Failed to retrieve user SID: %d\n", rc);
813         return rc;
814     }
815 
816     sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
817 
818     if (create)
819         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
820     else
821         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
822 
823     LocalFree(usersid);
824     return rc;
825 }
826 
827 UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
828 {
829     WCHAR squished_pc[GUID_SIZE];
830     WCHAR keypath[0x200];
831 
832     TRACE("%s\n", debugstr_w(szProduct));
833     if (!squash_guid(szProduct, squished_pc))
834         return ERROR_FUNCTION_FAILED;
835     TRACE("squished (%s)\n", debugstr_w(squished_pc));
836 
837     sprintfW(keypath, szUserDataProd_fmt, localsid, squished_pc);
838 
839     if (create)
840         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
841 
842     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
843 }
844 
845 static UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, LPCWSTR szUserSID,
846                                     HKEY *key, BOOL create)
847 {
848     UINT rc;
849     WCHAR squished_pc[GUID_SIZE];
850     WCHAR keypath[0x200];
851 
852     TRACE("%s\n", debugstr_w(szProduct));
853     if (!squash_guid(szProduct, squished_pc))
854         return ERROR_FUNCTION_FAILED;
855     TRACE("squished (%s)\n", debugstr_w(squished_pc));
856 
857     sprintfW(keypath, szInstallProperties_fmt, szUserSID, squished_pc);
858 
859     if (create)
860         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
861     else
862         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
863 
864     return rc;
865 }
866 
867 UINT MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct, HKEY *key,
868                                                BOOL create)
869 {
870     UINT rc;
871     LPWSTR usersid;
872 
873     rc = get_user_sid(&usersid);
874     if (rc != ERROR_SUCCESS || !usersid)
875     {
876         ERR("Failed to retrieve user SID: %d\n", rc);
877         return rc;
878     }
879 
880     rc = MSIREG_OpenInstallProps(szProduct, usersid, key, create);
881 
882     LocalFree(usersid);
883     return rc;
884 }
885 
886 UINT MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct, HKEY *key,
887                                         BOOL create)
888 {
889     return MSIREG_OpenInstallProps(szProduct, localsid, key, create);
890 }
891 
892 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
893 {
894     UINT rc;
895     WCHAR squished_pc[GUID_SIZE];
896     WCHAR keypath[0x200];
897     LPWSTR usersid;
898 
899     TRACE("%s\n", debugstr_w(szProduct));
900     if (!squash_guid(szProduct, squished_pc))
901         return ERROR_FUNCTION_FAILED;
902     TRACE("squished (%s)\n", debugstr_w(squished_pc));
903 
904     rc = get_user_sid(&usersid);
905     if (rc != ERROR_SUCCESS || !usersid)
906     {
907         ERR("Failed to retrieve user SID: %d\n", rc);
908         return rc;
909     }
910 
911     sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
912 
913     LocalFree(usersid);
914     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
915 }
916 
917 UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
918 {
919     UINT rc;
920     WCHAR squished_pc[GUID_SIZE];
921     WCHAR keypath[0x200];
922 
923     TRACE("%s\n",debugstr_w(szProduct));
924     if (!squash_guid(szProduct,squished_pc))
925         return ERROR_FUNCTION_FAILED;
926     TRACE("squished (%s)\n", debugstr_w(squished_pc));
927 
928     sprintfW(keypath,szInstaller_Products_fmt,squished_pc);
929 
930     if (create)
931         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
932     else
933         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
934 
935     return rc;
936 }
937 
938 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
939 {
940     WCHAR squished_pc[GUID_SIZE];
941     WCHAR keypath[0x200];
942 
943     TRACE("%s\n", debugstr_w(szProduct));
944     if (!squash_guid(szProduct, squished_pc))
945         return ERROR_FUNCTION_FAILED;
946     TRACE("squished (%s)\n", debugstr_w(squished_pc));
947 
948     sprintfW(keypath, szInstaller_Products_fmt, squished_pc);
949 
950     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
951 }
952 
953 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
954 {
955     UINT rc;
956     WCHAR squished_pc[GUID_SIZE];
957     WCHAR keypath[0x200];
958 
959     TRACE("%s\n",debugstr_w(szPatch));
960     if (!squash_guid(szPatch,squished_pc))
961         return ERROR_FUNCTION_FAILED;
962     TRACE("squished (%s)\n", debugstr_w(squished_pc));
963 
964     sprintfW(keypath,szInstaller_Patches_fmt,squished_pc);
965 
966     if (create)
967         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
968     else
969         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
970 
971     return rc;
972 }
973 
974 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
975 {
976     UINT rc;
977     WCHAR squished_pc[GUID_SIZE];
978     WCHAR keypath[0x200];
979 
980     TRACE("%s\n",debugstr_w(szUpgradeCode));
981     if (!squash_guid(szUpgradeCode,squished_pc))
982         return ERROR_FUNCTION_FAILED;
983     TRACE("squished (%s)\n", debugstr_w(squished_pc));
984 
985     sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
986 
987     if (create)
988         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
989     else
990         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
991 
992     return rc;
993 }
994 
995 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
996 {
997     UINT rc;
998     WCHAR squished_pc[GUID_SIZE];
999     WCHAR keypath[0x200];
1000 
1001     TRACE("%s\n",debugstr_w(szUpgradeCode));
1002     if (!squash_guid(szUpgradeCode,squished_pc))
1003         return ERROR_FUNCTION_FAILED;
1004     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1005 
1006     sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1007 
1008     if (create)
1009         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
1010     else
1011         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
1012 
1013     return rc;
1014 }
1015 
1016 UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
1017 {
1018     WCHAR squished_pc[GUID_SIZE];
1019     WCHAR keypath[0x200];
1020 
1021     TRACE("%s\n",debugstr_w(szUpgradeCode));
1022     if (!squash_guid(szUpgradeCode,squished_pc))
1023         return ERROR_FUNCTION_FAILED;
1024     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1025 
1026     sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1027 
1028     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
1029 }
1030 
1031 UINT MSIREG_OpenLocalSystemProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1032 {
1033     WCHAR squished_pc[GUID_SIZE];
1034     WCHAR keypath[0x200];
1035 
1036     TRACE("%s\n", debugstr_w(szProductCode));
1037 
1038     if (!squash_guid(szProductCode, squished_pc))
1039         return ERROR_FUNCTION_FAILED;
1040 
1041     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1042 
1043     sprintfW(keypath, szInstaller_LocalSystemProductCodes_fmt, squished_pc);
1044 
1045     if (create)
1046         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1047 
1048     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1049 }
1050 
1051 UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
1052 {
1053     WCHAR squished_pc[GUID_SIZE];
1054     WCHAR keypath[0x200];
1055 
1056     TRACE("%s\n", debugstr_w(szComponent));
1057 
1058     if (!squash_guid(szComponent, squished_pc))
1059         return ERROR_FUNCTION_FAILED;
1060 
1061     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1062 
1063     sprintfW(keypath, szInstaller_LocalSystemComponent_fmt, squished_pc);
1064 
1065     if (create)
1066         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1067 
1068     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1069 }
1070 
1071 UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1072 {
1073     WCHAR squished_pc[GUID_SIZE];
1074     WCHAR keypath[0x200];
1075 
1076     TRACE("%s\n", debugstr_w(szProductCode));
1077 
1078     if (!squash_guid(szProductCode, squished_pc))
1079         return ERROR_FUNCTION_FAILED;
1080 
1081     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1082 
1083     sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
1084 
1085     if (create)
1086         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1087 
1088     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1089 }
1090 
1091 UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1092 {
1093     WCHAR squished_pc[GUID_SIZE];
1094     WCHAR keypath[0x200];
1095 
1096     TRACE("%s\n", debugstr_w(szProductCode));
1097 
1098     if (!squash_guid(szProductCode, squished_pc))
1099         return ERROR_FUNCTION_FAILED;
1100 
1101     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1102 
1103     sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
1104 
1105     if (create)
1106         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1107 
1108     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1109 }
1110 
1111 UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1112 {
1113     WCHAR squished_pc[GUID_SIZE];
1114     WCHAR keypath[0x200];
1115     LPWSTR usersid;
1116     UINT r;
1117 
1118     TRACE("%s\n", debugstr_w(szProductCode));
1119 
1120     if (!squash_guid(szProductCode, squished_pc))
1121         return ERROR_FUNCTION_FAILED;
1122 
1123     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1124 
1125     r = get_user_sid(&usersid);
1126     if (r != ERROR_SUCCESS || !usersid)
1127     {
1128         ERR("Failed to retrieve user SID: %d\n", r);
1129         return r;
1130     }
1131 
1132     sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc);
1133     LocalFree(usersid);
1134 
1135     if (create)
1136         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1137 
1138     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1139 }
1140 
1141 UINT MSIREG_OpenManagedFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1142 {
1143     WCHAR squished_pc[GUID_SIZE];
1144     WCHAR keypath[0x200];
1145     LPWSTR usersid;
1146     UINT r;
1147 
1148     TRACE("%s\n", debugstr_w(szProductCode));
1149 
1150     if (!squash_guid(szProductCode, squished_pc))
1151         return ERROR_FUNCTION_FAILED;
1152 
1153     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1154 
1155     r = get_user_sid(&usersid);
1156     if (r != ERROR_SUCCESS || !usersid)
1157     {
1158         ERR("Failed to retrieve user SID: %d\n", r);
1159         return r;
1160     }
1161 
1162     sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc);
1163     LocalFree(usersid);
1164 
1165     if (create)
1166         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1167 
1168     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1169 }
1170 
1171 UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
1172 {
1173     WCHAR squished_pc[GUID_SIZE];
1174     WCHAR keypath[0x200];
1175 
1176     TRACE("%s\n", debugstr_w(szUpgradeCode));
1177     if (!squash_guid(szUpgradeCode, squished_pc))
1178         return ERROR_FUNCTION_FAILED;
1179     TRACE("squished (%s)\n", debugstr_w(squished_pc));
1180 
1181     sprintfW(keypath, szInstaller_ClassesUpgrade_fmt, squished_pc);
1182 
1183     if (create)
1184         return RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, key);
1185 
1186     return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key);
1187 }
1188 
1189 /*************************************************************************
1190  *  MsiDecomposeDescriptorW   [MSI.@]
1191  *
1192  * Decomposes an MSI descriptor into product, feature and component parts.
1193  * An MSI descriptor is a string of the form:
1194  *   [base 85 guid] [feature code] '>' [base 85 guid]
1195  *
1196  * PARAMS
1197  *   szDescriptor  [I]  the descriptor to decompose
1198  *   szProduct     [O]  buffer of MAX_FEATURE_CHARS+1 for the product guid
1199  *   szFeature     [O]  buffer of MAX_FEATURE_CHARS+1 for the feature code
1200  *   szComponent   [O]  buffer of MAX_FEATURE_CHARS+1 for the component guid
1201  *   pUsed         [O]  the length of the descriptor
1202  *
1203  * RETURNS
1204  *   ERROR_SUCCESS             if everything worked correctly
1205  *   ERROR_INVALID_PARAMETER   if the descriptor was invalid
1206  *
1207  */
1208 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
1209                 LPWSTR szFeature, LPWSTR szComponent, LPDWORD pUsed )
1210 {
1211     UINT r, len;
1212     LPWSTR p;
1213     GUID product, component;
1214 
1215     TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
1216           szFeature, szComponent, pUsed);
1217 
1218     r = decode_base85_guid( szDescriptor, &product );
1219     if( !r )
1220         return ERROR_INVALID_PARAMETER;
1221 
1222     TRACE("product %s\n", debugstr_guid( &product ));
1223 
1224     p = strchrW(&szDescriptor[20],'>');
1225     if( !p )
1226         return ERROR_INVALID_PARAMETER;
1227 
1228     len = (p - &szDescriptor[20]);
1229     if( len > MAX_FEATURE_CHARS )
1230         return ERROR_INVALID_PARAMETER;
1231 
1232     TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
1233 
1234     r = decode_base85_guid( p+1, &component );
1235     if( !r )
1236         return ERROR_INVALID_PARAMETER;
1237 
1238     TRACE("component %s\n", debugstr_guid( &component ));
1239 
1240     if (szProduct)
1241         StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
1242     if (szComponent)
1243         StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
1244     if (szFeature)
1245     {
1246         memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
1247         szFeature[len] = 0;
1248     }
1249     len = ( &p[21] - szDescriptor );
1250 
1251     TRACE("length = %d\n", len);
1252     *pUsed = len;
1253 
1254     return ERROR_SUCCESS;
1255 }
1256 
1257 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
1258                 LPSTR szFeature, LPSTR szComponent, LPDWORD pUsed )
1259 {
1260     WCHAR product[MAX_FEATURE_CHARS+1];
1261     WCHAR feature[MAX_FEATURE_CHARS+1];
1262     WCHAR component[MAX_FEATURE_CHARS+1];
1263     LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
1264     UINT r;
1265 
1266     TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
1267           szFeature, szComponent, pUsed);
1268 
1269     str = strdupAtoW( szDescriptor );
1270     if( szDescriptor && !str )
1271         return ERROR_OUTOFMEMORY;
1272 
1273     if (szProduct)
1274         p = product;
1275     if (szFeature)
1276         f = feature;
1277     if (szComponent)
1278         c = component;
1279 
1280     r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
1281 
1282     if (r == ERROR_SUCCESS)
1283     {
1284         WideCharToMultiByte( CP_ACP, 0, p, -1,
1285                              szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
1286         WideCharToMultiByte( CP_ACP, 0, f, -1,
1287                              szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
1288         WideCharToMultiByte( CP_ACP, 0, c, -1,
1289                              szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
1290     }
1291 
1292     msi_free( str );
1293 
1294     return r;
1295 }
1296 
1297 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
1298 {
1299     DWORD r;
1300     WCHAR szwGuid[GUID_SIZE];
1301 
1302     TRACE("%d %p\n", index, lpguid);
1303 
1304     if (NULL == lpguid)
1305         return ERROR_INVALID_PARAMETER;
1306     r = MsiEnumProductsW(index, szwGuid);
1307     if( r == ERROR_SUCCESS )
1308         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1309 
1310     return r;
1311 }
1312 
1313 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
1314 {
1315     HKEY hkeyProducts = 0;
1316     DWORD r;
1317     WCHAR szKeyName[SQUISH_GUID_SIZE];
1318 
1319     TRACE("%d %p\n", index, lpguid);
1320 
1321     if (NULL == lpguid)
1322         return ERROR_INVALID_PARAMETER;
1323 
1324     r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
1325     if( r != ERROR_SUCCESS )
1326         return ERROR_NO_MORE_ITEMS;
1327 
1328     r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
1329     if( r == ERROR_SUCCESS )
1330         unsquash_guid(szKeyName, lpguid);
1331     RegCloseKey(hkeyProducts);
1332 
1333     return r;
1334 }
1335 
1336 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
1337       LPSTR szFeature, LPSTR szParent)
1338 {
1339     DWORD r;
1340     WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
1341     LPWSTR szwProduct = NULL;
1342 
1343     TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
1344 
1345     if( szProduct )
1346     {
1347         szwProduct = strdupAtoW( szProduct );
1348         if( !szwProduct )
1349             return ERROR_OUTOFMEMORY;
1350     }
1351 
1352     r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
1353     if( r == ERROR_SUCCESS )
1354     {
1355         WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
1356                             szFeature, GUID_SIZE, NULL, NULL);
1357         WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
1358                             szParent, GUID_SIZE, NULL, NULL);
1359     }
1360 
1361     msi_free( szwProduct);
1362 
1363     return r;
1364 }
1365 
1366 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index, 
1367       LPWSTR szFeature, LPWSTR szParent)
1368 {
1369     HKEY hkeyProduct = 0;
1370     DWORD r, sz;
1371 
1372     TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
1373 
1374     if( !szProduct )
1375         return ERROR_INVALID_PARAMETER;
1376 
1377     r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE);
1378     if( r != ERROR_SUCCESS )
1379         return ERROR_NO_MORE_ITEMS;
1380 
1381     sz = GUID_SIZE;
1382     r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1383     RegCloseKey(hkeyProduct);
1384 
1385     return r;
1386 }
1387 
1388 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1389 {
1390     DWORD r;
1391     WCHAR szwGuid[GUID_SIZE];
1392 
1393     TRACE("%d %p\n", index, lpguid);
1394 
1395     r = MsiEnumComponentsW(index, szwGuid);
1396     if( r == ERROR_SUCCESS )
1397         WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1398 
1399     return r;
1400 }
1401 
1402 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1403 {
1404     HKEY hkeyComponents = 0;
1405     DWORD r;
1406     WCHAR szKeyName[SQUISH_GUID_SIZE];
1407 
1408     TRACE("%d %p\n", index, lpguid);
1409 
1410     r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Components, &hkeyComponents);
1411     if( r != ERROR_SUCCESS )
1412         return ERROR_NO_MORE_ITEMS;
1413 
1414     r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
1415     if( r == ERROR_SUCCESS )
1416         unsquash_guid(szKeyName, lpguid);
1417     RegCloseKey(hkeyComponents);
1418 
1419     return r;
1420 }
1421 
1422 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1423 {
1424     DWORD r;
1425     WCHAR szwProduct[GUID_SIZE];
1426     LPWSTR szwComponent = NULL;
1427 
1428     TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
1429 
1430     if ( !szProduct )
1431         return ERROR_INVALID_PARAMETER;
1432 
1433     if( szComponent )
1434     {
1435         szwComponent = strdupAtoW( szComponent );
1436         if( !szwComponent )
1437             return ERROR_OUTOFMEMORY;
1438     }
1439 
1440     r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1441     if( r == ERROR_SUCCESS )
1442     {
1443         WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1444                             szProduct, GUID_SIZE, NULL, NULL);
1445     }
1446 
1447     msi_free( szwComponent);
1448 
1449     return r;
1450 }
1451 
1452 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1453 {
1454     HKEY hkeyComp = 0;
1455     DWORD r, sz;
1456     WCHAR szValName[SQUISH_GUID_SIZE];
1457 
1458     TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
1459 
1460     if (!szComponent || !*szComponent || !szProduct)
1461         return ERROR_INVALID_PARAMETER;
1462 
1463     if (MSIREG_OpenUserDataComponentKey(szComponent, &hkeyComp, FALSE) != ERROR_SUCCESS &&
1464         MSIREG_OpenLocalSystemComponentKey(szComponent, &hkeyComp, FALSE) != ERROR_SUCCESS)
1465         return ERROR_UNKNOWN_COMPONENT;
1466 
1467     /* see if there are any products at all */
1468     sz = SQUISH_GUID_SIZE;
1469     r = RegEnumValueW(hkeyComp, 0, szValName, &sz, NULL, NULL, NULL, NULL);
1470     if (r != ERROR_SUCCESS)
1471     {
1472         RegCloseKey(hkeyComp);
1473 
1474         if (index != 0)
1475             return ERROR_INVALID_PARAMETER;
1476 
1477         return ERROR_UNKNOWN_COMPONENT;
1478     }
1479 
1480     sz = SQUISH_GUID_SIZE;
1481     r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1482     if( r == ERROR_SUCCESS )
1483         unsquash_guid(szValName, szProduct);
1484 
1485     RegCloseKey(hkeyComp);
1486 
1487     return r;
1488 }
1489 
1490 static UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
1491                 awstring *lpQualBuf, LPDWORD pcchQual,
1492                 awstring *lpAppBuf, LPDWORD pcchAppBuf )
1493 {
1494     DWORD name_sz, val_sz, name_max, val_max, type, ofs;
1495     LPWSTR name = NULL, val = NULL;
1496     UINT r, r2;
1497     HKEY key;
1498 
1499     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1500           lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
1501 
1502     if (!szComponent)
1503         return ERROR_INVALID_PARAMETER;
1504 
1505     r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1506     if (r != ERROR_SUCCESS)
1507         return ERROR_UNKNOWN_COMPONENT;
1508 
1509     /* figure out how big the name is we want to return */
1510     name_max = 0x10;
1511     r = ERROR_OUTOFMEMORY;
1512     name = msi_alloc( name_max * sizeof(WCHAR) );
1513     if (!name)
1514         goto end;
1515 
1516     val_max = 0x10;
1517     r = ERROR_OUTOFMEMORY;
1518     val = msi_alloc( val_max );
1519     if (!val)
1520         goto end;
1521 
1522     /* loop until we allocate enough memory */
1523     while (1)
1524     {
1525         name_sz = name_max;
1526         val_sz = val_max;
1527         r = RegEnumValueW( key, iIndex, name, &name_sz,
1528                            NULL, &type, (LPBYTE)val, &val_sz );
1529         if (r == ERROR_SUCCESS)
1530             break;
1531         if (r != ERROR_MORE_DATA)
1532             goto end;
1533  
1534         if (type != REG_MULTI_SZ)
1535         {
1536             ERR("component data has wrong type (%d)\n", type);
1537             goto end;
1538         }
1539 
1540         r = ERROR_OUTOFMEMORY;
1541         if ((name_sz+1) >= name_max)
1542         {
1543             name_max *= 2;
1544             msi_free( name );
1545             name = msi_alloc( name_max * sizeof (WCHAR) );
1546             if (!name)
1547                 goto end;
1548             continue;
1549         }
1550         if (val_sz > val_max)
1551         {
1552             val_max = val_sz + sizeof (WCHAR);
1553             msi_free( val );
1554             val = msi_alloc( val_max * sizeof (WCHAR) );
1555             if (!val)
1556                 goto end;
1557             continue;
1558         }
1559         ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
1560         goto end;
1561     }
1562 
1563     ofs = 0;
1564     r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1565     if (r != ERROR_SUCCESS)
1566         goto end;
1567 
1568     TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1569 
1570     r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
1571     r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
1572 
1573     if (r2 != ERROR_SUCCESS)
1574         r = r2;
1575 
1576 end:
1577     msi_free(val);
1578     msi_free(name);
1579     RegCloseKey(key);
1580 
1581     return r;
1582 }
1583 
1584 /*************************************************************************
1585  *  MsiEnumComponentQualifiersA [MSI.@]
1586  */
1587 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
1588                 LPSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1589                 LPSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1590 {
1591     awstring qual, appdata;
1592     LPWSTR comp;
1593     UINT r;
1594 
1595     TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
1596           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1597           pcchApplicationDataBuf);
1598 
1599     comp = strdupAtoW( szComponent );
1600     if (szComponent && !comp)
1601         return ERROR_OUTOFMEMORY;
1602 
1603     qual.unicode = FALSE;
1604     qual.str.a = lpQualifierBuf;
1605 
1606     appdata.unicode = FALSE;
1607     appdata.str.a = lpApplicationDataBuf;
1608 
1609     r = MSI_EnumComponentQualifiers( comp, iIndex,
1610               &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1611     msi_free( comp );
1612     return r;
1613 }
1614 
1615 /*************************************************************************
1616  *  MsiEnumComponentQualifiersW [MSI.@]
1617  */
1618 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
1619                 LPWSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1620                 LPWSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1621 {
1622     awstring qual, appdata;
1623 
1624     TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1625           lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1626           pcchApplicationDataBuf);
1627 
1628     qual.unicode = TRUE;
1629     qual.str.w = lpQualifierBuf;
1630 
1631     appdata.unicode = TRUE;
1632     appdata.str.w = lpApplicationDataBuf;
1633 
1634     return MSI_EnumComponentQualifiers( szComponent, iIndex,
1635                  &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1636 }
1637 
1638 /*************************************************************************
1639  *  MsiEnumRelatedProductsW   [MSI.@]
1640  *
1641  */
1642 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
1643                                     DWORD iProductIndex, LPWSTR lpProductBuf)
1644 {
1645     UINT r;
1646     HKEY hkey;
1647     DWORD dwSize = SQUISH_GUID_SIZE;
1648     WCHAR szKeyName[SQUISH_GUID_SIZE];
1649 
1650     TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
1651           iProductIndex, lpProductBuf);
1652 
1653     if (NULL == szUpgradeCode)
1654         return ERROR_INVALID_PARAMETER;
1655     if (NULL == lpProductBuf)
1656         return ERROR_INVALID_PARAMETER;
1657 
1658     r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1659     if (r != ERROR_SUCCESS)
1660         return ERROR_NO_MORE_ITEMS;
1661 
1662     r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1663     if( r == ERROR_SUCCESS )
1664         unsquash_guid(szKeyName, lpProductBuf);
1665     RegCloseKey(hkey);
1666 
1667     return r;
1668 }
1669 
1670 /*************************************************************************
1671  *  MsiEnumRelatedProductsA   [MSI.@]
1672  *
1673  */
1674 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
1675                                     DWORD iProductIndex, LPSTR lpProductBuf)
1676 {
1677     LPWSTR szwUpgradeCode = NULL;
1678     WCHAR productW[GUID_SIZE];
1679     UINT r;
1680 
1681     TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
1682           iProductIndex, lpProductBuf);
1683 
1684     if (szUpgradeCode)
1685     {
1686         szwUpgradeCode = strdupAtoW( szUpgradeCode );
1687         if( !szwUpgradeCode )
1688             return ERROR_OUTOFMEMORY;
1689     }
1690 
1691     r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1692                                  iProductIndex, productW );
1693     if (r == ERROR_SUCCESS)
1694     {
1695         WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1696                              lpProductBuf, GUID_SIZE, NULL, NULL );
1697     }
1698     msi_free( szwUpgradeCode);
1699     return r;
1700 }
1701 
1702 /***********************************************************************
1703  * MsiEnumPatchesA            [MSI.@]
1704  */
1705 UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
1706         LPSTR lpPatchBuf, LPSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
1707 {
1708     FIXME("%s %d %p %p %p\n", debugstr_a(szProduct),
1709           iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1710     return ERROR_NO_MORE_ITEMS;
1711 }
1712 
1713 /***********************************************************************
1714  * MsiEnumPatchesW            [MSI.@]
1715  */
1716 UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
1717         LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
1718 {
1719     FIXME("%s %d %p %p %p\n", debugstr_w(szProduct),
1720           iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1721     return ERROR_NO_MORE_ITEMS;
1722 }
1723 
1724 UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
1725         DWORD dwContext, DWORD dwIndex, CHAR szInstalledProductCode[39],
1726         MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
1727 {
1728     FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
1729           dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1730           szSid, pcchSid);
1731     return ERROR_NO_MORE_ITEMS;
1732 }
1733 
1734 UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
1735         DWORD dwContext, DWORD dwIndex, WCHAR szInstalledProductCode[39],
1736         MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
1737 {
1738     FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
1739           dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1740           szSid, pcchSid);
1741     return ERROR_NO_MORE_ITEMS;
1742 }
1743 

~ [ 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.