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

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

Version: ~ [ 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 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
529                            HKEY *key, BOOL create)
530 {
531     UINT r;
532     LPWSTR usersid;
533     HKEY root = HKEY_LOCAL_MACHINE;
534     WCHAR squished_pc[GUID_SIZE];
535     WCHAR keypath[MAX_PATH];
536 
537     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
538 
539     if (!squash_guid(szProduct, squished_pc))
540         return ERROR_FUNCTION_FAILED;
541 
542     TRACE("squished (%s)\n", debugstr_w(squished_pc));
543 
544     if (context == MSIINSTALLCONTEXT_MACHINE)
545     {
546         sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
547     }
548     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
549     {
550         root = HKEY_CURRENT_USER;
551         sprintfW(keypath, szUserProduct_fmt, squished_pc);
552     }
553     else
554     {
555         r = get_user_sid(&usersid);
556         if (r != ERROR_SUCCESS || !usersid)
557         {
558             ERR("Failed to retrieve user SID: %d\n", r);
559             return r;
560         }
561 
562         sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc);
563         LocalFree(usersid);
564     }
565 
566     if (create)
567         return RegCreateKeyW(root, keypath, key);
568 
569     return RegOpenKeyW(root, keypath, key);
570 }
571 
572 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
573 {
574     WCHAR squished_pc[GUID_SIZE];
575     WCHAR keypath[0x200];
576 
577     TRACE("%s\n",debugstr_w(szProduct));
578     if (!squash_guid(szProduct,squished_pc))
579         return ERROR_FUNCTION_FAILED;
580     TRACE("squished (%s)\n", debugstr_w(squished_pc));
581 
582     sprintfW(keypath,szUserProduct_fmt,squished_pc);
583 
584     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
585 }
586 
587 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
588 {
589     UINT rc;
590     WCHAR squished_pc[GUID_SIZE];
591     WCHAR keypath[0x200];
592 
593     TRACE("%s\n",debugstr_w(szPatch));
594     if (!squash_guid(szPatch,squished_pc))
595         return ERROR_FUNCTION_FAILED;
596     TRACE("squished (%s)\n", debugstr_w(squished_pc));
597 
598     sprintfW(keypath,szUserPatch_fmt,squished_pc);
599 
600     if (create)
601         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
602     else
603         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
604 
605     return rc;
606 }
607 
608 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
609                             HKEY *key, BOOL create)
610 {
611     UINT r;
612     LPWSTR usersid;
613     HKEY root = HKEY_LOCAL_MACHINE;
614     WCHAR squished_pc[GUID_SIZE];
615     WCHAR keypath[MAX_PATH];
616 
617     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
618 
619     if (!squash_guid(szProduct, squished_pc))
620         return ERROR_FUNCTION_FAILED;
621 
622     TRACE("squished (%s)\n", debugstr_w(squished_pc));
623 
624     if (context == MSIINSTALLCONTEXT_MACHINE)
625     {
626         sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
627     }
628     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
629     {
630         root = HKEY_CURRENT_USER;
631         sprintfW(keypath, szUserFeatures_fmt, squished_pc);
632     }
633     else
634     {
635         r = get_user_sid(&usersid);
636         if (r != ERROR_SUCCESS || !usersid)
637         {
638             ERR("Failed to retrieve user SID: %d\n", r);
639             return r;
640         }
641 
642         sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc);
643         LocalFree(usersid);
644     }
645 
646     if (create)
647         return RegCreateKeyW(root, keypath, key);
648 
649     return RegOpenKeyW(root, keypath, key);
650 }
651 
652 UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
653 {
654     WCHAR squished_pc[GUID_SIZE];
655     WCHAR keypath[0x200];
656 
657     TRACE("%s\n",debugstr_w(szProduct));
658     if (!squash_guid(szProduct,squished_pc))
659         return ERROR_FUNCTION_FAILED;
660     TRACE("squished (%s)\n", debugstr_w(squished_pc));
661 
662     sprintfW(keypath,szUserFeatures_fmt,squished_pc);
663     return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
664 }
665 
666 UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
667 {
668     UINT rc;
669     WCHAR squished_pc[GUID_SIZE];
670     WCHAR keypath[0x200];
671 
672     TRACE("%s\n",debugstr_w(szProduct));
673     if (!squash_guid(szProduct,squished_pc))
674         return ERROR_FUNCTION_FAILED;
675     TRACE("squished (%s)\n", debugstr_w(squished_pc));
676 
677     sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
678 
679     if (create)
680         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
681     else
682         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
683 
684     return rc;
685 }
686 
687 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
688                                     HKEY *key, BOOL create)
689 {
690     UINT r;
691     LPWSTR usersid;
692     WCHAR squished_pc[GUID_SIZE];
693     WCHAR keypath[0x200];
694 
695     TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
696 
697     if (!squash_guid(szProduct, squished_pc))
698         return ERROR_FUNCTION_FAILED;
699 
700     TRACE("squished (%s)\n", debugstr_w(squished_pc));
701 
702     if (context == MSIINSTALLCONTEXT_MACHINE)
703     {
704         sprintfW(keypath, szUserDataFeatures_fmt, localsid, squished_pc);
705     }
706     else
707     {
708         r = get_user_sid(&usersid);
709         if (r != ERROR_SUCCESS || !usersid)
710         {
711             ERR("Failed to retrieve user SID: %d\n", r);
712             return r;
713         }
714 
715         sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
716         LocalFree(usersid);
717     }
718 
719     if (create)
720         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
721 
722     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
723 }
724 
725 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
726 {
727     UINT rc;
728     WCHAR squished_cc[GUID_SIZE];
729     WCHAR keypath[0x200];
730 
731     TRACE("%s\n",debugstr_w(szComponent));
732     if (!squash_guid(szComponent,squished_cc))
733         return ERROR_FUNCTION_FAILED;
734     TRACE("squished (%s)\n", debugstr_w(squished_cc));
735 
736     sprintfW(keypath,szUser_Components_fmt,squished_cc);
737 
738     if (create)
739         rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
740     else
741         rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
742 
743     return rc;
744 }
745 
746 UINT MSIREG_OpenLocalUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
747 {
748     WCHAR comp[GUID_SIZE];
749     WCHAR keypath[0x200];
750 
751     TRACE("%s\n", debugstr_w(szComponent));
752     if (!squash_guid(szComponent, comp))
753         return ERROR_FUNCTION_FAILED;
754     TRACE("squished (%s)\n", debugstr_w(comp));
755 
756     sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
757 
758     if (create)
759         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
760 
761     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
762 }
763 
764 UINT MSIREG_DeleteLocalUserDataComponentKey(LPCWSTR szComponent)
765 {
766     WCHAR comp[GUID_SIZE];
767     WCHAR keypath[0x200];
768 
769     TRACE("%s\n", debugstr_w(szComponent));
770     if (!squash_guid(szComponent, comp))
771         return ERROR_FUNCTION_FAILED;
772     TRACE("squished (%s)\n", debugstr_w(comp));
773 
774     sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
775     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
776 }
777 
778 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
779 {
780     UINT rc;
781     WCHAR comp[GUID_SIZE];
782     WCHAR keypath[0x200];
783     LPWSTR usersid;
784 
785     TRACE("%s\n", debugstr_w(szComponent));
786     if (!squash_guid(szComponent, comp))
787         return ERROR_FUNCTION_FAILED;
788     TRACE("squished (%s)\n", debugstr_w(comp));
789 
790     rc = get_user_sid(&usersid);
791     if (rc != ERROR_SUCCESS || !usersid)
792     {
793         ERR("Failed to retrieve user SID: %d\n", rc);
794         return rc;
795     }
796 
797     sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
798 
799     if (create)
800         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
801     else
802         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
803 
804     LocalFree(usersid);
805     return rc;
806 }
807 
808 UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent)
809 {
810     UINT rc;
811     WCHAR comp[GUID_SIZE];
812     WCHAR keypath[0x200];
813     LPWSTR usersid;
814 
815     TRACE("%s\n", debugstr_w(szComponent));
816     if (!squash_guid(szComponent, comp))
817         return ERROR_FUNCTION_FAILED;
818     TRACE("squished (%s)\n", debugstr_w(comp));
819 
820     rc = get_user_sid(&usersid);
821     if (rc != ERROR_SUCCESS || !usersid)
822     {
823         ERR("Failed to retrieve user SID: %d\n", rc);
824         return rc;
825     }
826 
827     sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
828 
829     LocalFree(usersid);
830     return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
831 }
832 
833 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
834 {
835     UINT rc;
836     WCHAR squished_pc[GUID_SIZE];
837     WCHAR keypath[0x200];
838     LPWSTR usersid;
839 
840     TRACE("%s\n", debugstr_w(szProduct));
841     if (!squash_guid(szProduct, squished_pc))
842         return ERROR_FUNCTION_FAILED;
843     TRACE("squished (%s)\n", debugstr_w(squished_pc));
844 
845     rc = get_user_sid(&usersid);
846     if (rc != ERROR_SUCCESS || !usersid)
847     {
848         ERR("Failed to retrieve user SID: %d\n", rc);
849         return rc;
850     }
851 
852     sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
853 
854     if (create)
855         rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
856     else
857         rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
858 
859     LocalFree(usersid);
860     return rc;
861 }
862 
863 UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
864 {
865     WCHAR squished_pc[GUID_SIZE];
866     WCHAR keypath[0x200];
867 
868     TRACE("%s\n", debugstr_w(szProduct));
869     if (!squash_guid(szProduct, squished_pc))
870         return ERROR_FUNCTION_FAILED;
871     TRACE("squished (%s)\n", debugstr_w(squished_pc));
872 
873     sprintfW(keypath, szUserDataProd_fmt, localsid, squished_pc);
874 
875     if (create)
876         return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
877 
878     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
879 }
880 
881 static UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, LPCWSTR szUserSID,
882                                     HKEY *key, BOOL create)
883 {
884     UINT rc;
885     WCHAR squished_pc[GUID_SIZE];
886     WCHAR keypath[0x200];
887 
888     TRACE("%s\n", debugstr_w(szProduct));
889     if (!squash_guid(szProduct, squished_pc))
890         return ERROR_FUNCTION_FAILED;
891     TRACE("squished (%s)\n", debugstr_w(squished_pc));
892