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