msi: Fix an uninitialized variable.
[wine/multimedia.git] / dlls / msi / registry.c
blobb413b6f768e6675aa8a862e5fd23a113cbb47f0b
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 * Copyright 2005 Aric Stewart for CodeWeavers
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.
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.
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
22 #include <stdarg.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
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"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
44 /*
45 * This module will be all the helper functions for registry access by the
46 * installer bits.
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};
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};
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};
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 };
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};
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};
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 };
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};
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};
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};
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};
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};
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};
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};
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};
171 static const WCHAR szUserDataPatch_fmt[] = {
172 'S','o','f','t','w','a','r','e','\\',
173 'M','i','c','r','o','s','o','f','t','\\',
174 'W','i','n','d','o','w','s','\\',
175 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
176 'I','n','s','t','a','l','l','e','r','\\',
177 'U','s','e','r','D','a','t','a','\\',
178 '%','s','\\','P','a','t','c','h','e','s','\\','%','s',0};
180 static const WCHAR szInstallProperties_fmt[] = {
181 'S','o','f','t','w','a','r','e','\\',
182 'M','i','c','r','o','s','o','f','t','\\',
183 'W','i','n','d','o','w','s','\\',
184 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
185 'I','n','s','t','a','l','l','e','r','\\',
186 'U','s','e','r','D','a','t','a','\\',
187 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
188 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
190 static const WCHAR szInstaller_LocalSystemProductCodes_fmt[] = {
191 'S','o','f','t','w','a','r','e','\\',
192 'M','i','c','r','o','s','o','f','t','\\',
193 'W','i','n','d','o','w','s','\\',
194 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
195 'I','n','s','t','a','l','l','e','r','\\',
196 'U','s','e','r','D','a','t','a','\\',
197 'S','-','1','-','5','-','1','8','\\','P','r','o','d','u','c','t','s','\\',
198 '%','s','\\','I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
200 static const WCHAR szInstaller_LocalSystemComponent_fmt[] = {
201 'S','o','f','t','w','a','r','e','\\',
202 'M','i','c','r','o','s','o','f','t','\\',
203 'W','i','n','d','o','w','s','\\',
204 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
205 'I','n','s','t','a','l','l','e','r','\\',
206 'U','s','e','r','D','a','t','a','\\',
207 'S','-','1','-','5','-','1','8','\\',
208 'C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
210 static const WCHAR szInstaller_LocalClassesProd_fmt[] = {
211 'S','o','f','t','w','a','r','e','\\',
212 'C','l','a','s','s','e','s','\\',
213 'I','n','s','t','a','l','l','e','r','\\',
214 'P','r','o','d','u','c','t','s','\\','%','s',0};
216 static const WCHAR szInstaller_LocalClassesFeat_fmt[] = {
217 'S','o','f','t','w','a','r','e','\\',
218 'C','l','a','s','s','e','s','\\',
219 'I','n','s','t','a','l','l','e','r','\\',
220 'F','e','a','t','u','r','e','s','\\','%','s',0};
222 static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
223 'S','o','f','t','w','a','r','e','\\',
224 'M','i','c','r','o','s','o','f','t','\\',
225 'W','i','n','d','o','w','s','\\',
226 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
227 'I','n','s','t','a','l','l','e','r','\\',
228 'M','a','n','a','g','e','d','\\','%','s','\\',
229 'I','n','s','t','a','l','l','e','r','\\',
230 'P','r','o','d','u','c','t','s','\\','%','s',0};
232 static const WCHAR szInstaller_LocalManagedFeat_fmt[] = {
233 'S','o','f','t','w','a','r','e','\\',
234 'M','i','c','r','o','s','o','f','t','\\',
235 'W','i','n','d','o','w','s','\\',
236 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
237 'I','n','s','t','a','l','l','e','r','\\',
238 'M','a','n','a','g','e','d','\\','%','s','\\',
239 'I','n','s','t','a','l','l','e','r','\\',
240 'F','e','a','t','u','r','e','s','\\','%','s',0};
242 static const WCHAR szInstaller_ClassesUpgrade_fmt[] = {
243 'I','n','s','t','a','l','l','e','r','\\',
244 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
245 '%','s',0};
247 static const WCHAR localsid[] = {'S','-','1','-','5','-','1','8',0};
249 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
251 DWORD i,n=0;
253 if (lstrlenW(in) != 32)
254 return FALSE;
256 out[n++]='{';
257 for(i=0; i<8; i++)
258 out[n++] = in[7-i];
259 out[n++]='-';
260 for(i=0; i<4; i++)
261 out[n++] = in[11-i];
262 out[n++]='-';
263 for(i=0; i<4; i++)
264 out[n++] = in[15-i];
265 out[n++]='-';
266 for(i=0; i<2; i++)
268 out[n++] = in[17+i*2];
269 out[n++] = in[16+i*2];
271 out[n++]='-';
272 for( ; i<8; i++)
274 out[n++] = in[17+i*2];
275 out[n++] = in[16+i*2];
277 out[n++]='}';
278 out[n]=0;
279 return TRUE;
282 BOOL squash_guid(LPCWSTR in, LPWSTR out)
284 DWORD i,n=1;
285 GUID guid;
287 out[0] = 0;
289 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
290 return FALSE;
292 for(i=0; i<8; i++)
293 out[7-i] = in[n++];
294 n++;
295 for(i=0; i<4; i++)
296 out[11-i] = in[n++];
297 n++;
298 for(i=0; i<4; i++)
299 out[15-i] = in[n++];
300 n++;
301 for(i=0; i<2; i++)
303 out[17+i*2] = in[n++];
304 out[16+i*2] = in[n++];
306 n++;
307 for( ; i<8; i++)
309 out[17+i*2] = in[n++];
310 out[16+i*2] = in[n++];
312 out[32]=0;
313 return TRUE;
317 /* tables for encoding and decoding base85 */
318 static const unsigned char table_dec85[0x80] = {
319 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
320 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
321 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
322 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
323 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
324 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
325 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
326 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
329 static const char table_enc85[] =
330 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
331 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
332 "yz{}~";
335 * Converts a base85 encoded guid into a GUID pointer
336 * Base85 encoded GUIDs should be 20 characters long.
338 * returns TRUE if successful, FALSE if not
340 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
342 DWORD i, val = 0, base = 1, *p;
344 if (!str)
345 return FALSE;
347 p = (DWORD*) guid;
348 for( i=0; i<20; i++ )
350 if( (i%5) == 0 )
352 val = 0;
353 base = 1;
355 val += table_dec85[str[i]] * base;
356 if( str[i] >= 0x80 )
357 return FALSE;
358 if( table_dec85[str[i]] == 0xff )
359 return FALSE;
360 if( (i%5) == 4 )
361 p[i/5] = val;
362 base *= 85;
364 return TRUE;
368 * Encodes a base85 guid given a GUID pointer
369 * Caller should provide a 21 character buffer for the encoded string.
371 * returns TRUE if successful, FALSE if not
373 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
375 unsigned int x, *p, i;
377 p = (unsigned int*) guid;
378 for( i=0; i<4; i++ )
380 x = p[i];
381 *str++ = table_enc85[x%85];
382 x = x/85;
383 *str++ = table_enc85[x%85];
384 x = x/85;
385 *str++ = table_enc85[x%85];
386 x = x/85;
387 *str++ = table_enc85[x%85];
388 x = x/85;
389 *str++ = table_enc85[x%85];
391 *str = 0;
393 return TRUE;
396 DWORD msi_version_str_to_dword(LPCWSTR p)
398 DWORD major, minor = 0, build = 0, version = 0;
400 if (!p)
401 return version;
403 major = atoiW(p);
405 p = strchrW(p, '.');
406 if (p)
408 minor = atoiW(p+1);
409 p = strchrW(p+1, '.');
410 if (p)
411 build = atoiW(p+1);
414 return MAKELONG(build, MAKEWORD(minor, major));
417 LPWSTR msi_version_dword_to_str(DWORD version)
419 static const WCHAR fmt[] = { '%','u','.','%','u','.','%','u',0 };
420 LPWSTR str = msi_alloc(20);
421 sprintfW(str, fmt,
422 (version&0xff000000)>>24,
423 (version&0x00ff0000)>>16,
424 version&0x0000ffff);
425 return str;
428 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
430 static const WCHAR emptyW[] = {0};
431 DWORD len;
432 if (!value) value = emptyW;
433 len = (lstrlenW(value) + 1) * sizeof (WCHAR);
434 return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
437 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
439 LPCWSTR p = value;
440 while (*p) p += lstrlenW(p) + 1;
441 return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
442 (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
445 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
447 return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
450 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
452 HKEY hsubkey = 0;
453 LONG r;
455 r = RegCreateKeyW( hkey, path, &hsubkey );
456 if (r != ERROR_SUCCESS)
457 return r;
458 r = msi_reg_set_val_str( hsubkey, name, val );
459 RegCloseKey( hsubkey );
460 return r;
463 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
465 DWORD len = 0;
466 LPWSTR val;
467 LONG r;
469 r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
470 if (r != ERROR_SUCCESS)
471 return NULL;
473 len += sizeof (WCHAR);
474 val = msi_alloc( len );
475 if (!val)
476 return NULL;
477 val[0] = 0;
478 RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
479 return val;
482 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
484 DWORD type, len = sizeof (DWORD);
485 LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
486 return r == ERROR_SUCCESS && type == REG_DWORD;
489 static UINT get_user_sid(LPWSTR *usersid)
491 HANDLE token;
492 BYTE buf[1024];
493 DWORD size;
494 PTOKEN_USER user;
496 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
497 return ERROR_FUNCTION_FAILED;
499 size = sizeof(buf);
500 if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size)) {
501 CloseHandle(token);
502 return ERROR_FUNCTION_FAILED;
505 user = (PTOKEN_USER)buf;
506 if (!ConvertSidToStringSidW(user->User.Sid, usersid)) {
507 CloseHandle(token);
508 return ERROR_FUNCTION_FAILED;
510 CloseHandle(token);
511 return ERROR_SUCCESS;
514 UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
516 UINT rc;
517 WCHAR keypath[0x200];
518 TRACE("%s\n",debugstr_w(szProduct));
520 sprintfW(keypath,szUninstall_fmt,szProduct);
522 if (create)
523 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
524 else
525 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
527 return rc;
530 UINT MSIREG_DeleteUninstallKey(LPCWSTR szProduct)
532 WCHAR keypath[0x200];
533 TRACE("%s\n",debugstr_w(szProduct));
535 sprintfW(keypath,szUninstall_fmt,szProduct);
537 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
540 UINT MSIREG_OpenProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
541 HKEY *key, BOOL create)
543 UINT r;
544 LPWSTR usersid;
545 HKEY root = HKEY_LOCAL_MACHINE;
546 WCHAR squished_pc[GUID_SIZE];
547 WCHAR keypath[MAX_PATH];
549 TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
551 if (!squash_guid(szProduct, squished_pc))
552 return ERROR_FUNCTION_FAILED;
554 TRACE("squished (%s)\n", debugstr_w(squished_pc));
556 if (context == MSIINSTALLCONTEXT_MACHINE)
558 sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
560 else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
562 root = HKEY_CURRENT_USER;
563 sprintfW(keypath, szUserProduct_fmt, squished_pc);
565 else
567 r = get_user_sid(&usersid);
568 if (r != ERROR_SUCCESS || !usersid)
570 ERR("Failed to retrieve user SID: %d\n", r);
571 return r;
574 sprintfW(keypath, szInstaller_LocalManagedProd_fmt, usersid, squished_pc);
575 LocalFree(usersid);
578 if (create)
579 return RegCreateKeyW(root, keypath, key);
581 return RegOpenKeyW(root, keypath, key);
584 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
586 WCHAR squished_pc[GUID_SIZE];
587 WCHAR keypath[0x200];
589 TRACE("%s\n",debugstr_w(szProduct));
590 if (!squash_guid(szProduct,squished_pc))
591 return ERROR_FUNCTION_FAILED;
592 TRACE("squished (%s)\n", debugstr_w(squished_pc));
594 sprintfW(keypath,szUserProduct_fmt,squished_pc);
596 return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
599 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
601 UINT rc;
602 WCHAR squished_pc[GUID_SIZE];
603 WCHAR keypath[0x200];
605 TRACE("%s\n",debugstr_w(szPatch));
606 if (!squash_guid(szPatch,squished_pc))
607 return ERROR_FUNCTION_FAILED;
608 TRACE("squished (%s)\n", debugstr_w(squished_pc));
610 sprintfW(keypath,szUserPatch_fmt,squished_pc);
612 if (create)
613 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
614 else
615 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
617 return rc;
620 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
621 HKEY *key, BOOL create)
623 UINT r;
624 LPWSTR usersid;
625 HKEY root = HKEY_LOCAL_MACHINE;
626 WCHAR squished_pc[GUID_SIZE];
627 WCHAR keypath[MAX_PATH];
629 TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
631 if (!squash_guid(szProduct, squished_pc))
632 return ERROR_FUNCTION_FAILED;
634 TRACE("squished (%s)\n", debugstr_w(squished_pc));
636 if (context == MSIINSTALLCONTEXT_MACHINE)
638 sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
640 else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
642 root = HKEY_CURRENT_USER;
643 sprintfW(keypath, szUserFeatures_fmt, squished_pc);
645 else
647 r = get_user_sid(&usersid);
648 if (r != ERROR_SUCCESS || !usersid)
650 ERR("Failed to retrieve user SID: %d\n", r);
651 return r;
654 sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc);
655 LocalFree(usersid);
658 if (create)
659 return RegCreateKeyW(root, keypath, key);
661 return RegOpenKeyW(root, keypath, key);
664 UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
666 WCHAR squished_pc[GUID_SIZE];
667 WCHAR keypath[0x200];
669 TRACE("%s\n",debugstr_w(szProduct));
670 if (!squash_guid(szProduct,squished_pc))
671 return ERROR_FUNCTION_FAILED;
672 TRACE("squished (%s)\n", debugstr_w(squished_pc));
674 sprintfW(keypath,szUserFeatures_fmt,squished_pc);
675 return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
678 UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
680 UINT rc;
681 WCHAR squished_pc[GUID_SIZE];
682 WCHAR keypath[0x200];
684 TRACE("%s\n",debugstr_w(szProduct));
685 if (!squash_guid(szProduct,squished_pc))
686 return ERROR_FUNCTION_FAILED;
687 TRACE("squished (%s)\n", debugstr_w(squished_pc));
689 sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
691 if (create)
692 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
693 else
694 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
696 return rc;
699 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context,
700 HKEY *key, BOOL create)
702 UINT r;
703 LPWSTR usersid;
704 WCHAR squished_pc[GUID_SIZE];
705 WCHAR keypath[0x200];
707 TRACE("(%s, %d, %d)\n", debugstr_w(szProduct), context, create);
709 if (!squash_guid(szProduct, squished_pc))
710 return ERROR_FUNCTION_FAILED;
712 TRACE("squished (%s)\n", debugstr_w(squished_pc));
714 if (context == MSIINSTALLCONTEXT_MACHINE)
716 sprintfW(keypath, szUserDataFeatures_fmt, localsid, squished_pc);
718 else
720 r = get_user_sid(&usersid);
721 if (r != ERROR_SUCCESS || !usersid)
723 ERR("Failed to retrieve user SID: %d\n", r);
724 return r;
727 sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
728 LocalFree(usersid);
731 if (create)
732 return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
734 return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
737 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
739 UINT rc;
740 WCHAR squished_cc[GUID_SIZE];
741 WCHAR keypath[0x200];
743 TRACE("%s\n",debugstr_w(szComponent));
744 if (!squash_guid(szComponent,squished_cc))
745 return ERROR_FUNCTION_FAILED;
746 TRACE("squished (%s)\n", debugstr_w(squished_cc));
748 sprintfW(keypath,szUser_Components_fmt,squished_cc);
750 if (create)
751 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
752 else
753 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
755 return rc;
758 UINT MSIREG_OpenLocalUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
760 WCHAR comp[GUID_SIZE];
761 WCHAR keypath[0x200];
763 TRACE("%s\n", debugstr_w(szComponent));
764 if (!squash_guid(szComponent, comp))
765 return ERROR_FUNCTION_FAILED;
766 TRACE("squished (%s)\n", debugstr_w(comp));
768 sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
770 if (create)
771 return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
773 return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
776 UINT MSIREG_DeleteLocalUserDataComponentKey(LPCWSTR szComponent)
778 WCHAR comp[GUID_SIZE];
779 WCHAR keypath[0x200];
781 TRACE("%s\n", debugstr_w(szComponent));
782 if (!squash_guid(szComponent, comp))
783 return ERROR_FUNCTION_FAILED;
784 TRACE("squished (%s)\n", debugstr_w(comp));
786 sprintfW(keypath, szUserDataComp_fmt, localsid, comp);
787 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
790 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
792 UINT rc;
793 WCHAR comp[GUID_SIZE];
794 WCHAR keypath[0x200];
795 LPWSTR usersid;
797 TRACE("%s\n", debugstr_w(szComponent));
798 if (!squash_guid(szComponent, comp))
799 return ERROR_FUNCTION_FAILED;
800 TRACE("squished (%s)\n", debugstr_w(comp));
802 rc = get_user_sid(&usersid);
803 if (rc != ERROR_SUCCESS || !usersid)
805 ERR("Failed to retrieve user SID: %d\n", rc);
806 return rc;
809 sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
811 if (create)
812 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
813 else
814 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
816 LocalFree(usersid);
817 return rc;
820 UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent)
822 UINT rc;
823 WCHAR comp[GUID_SIZE];
824 WCHAR keypath[0x200];
825 LPWSTR usersid;
827 TRACE("%s\n", debugstr_w(szComponent));
828 if (!squash_guid(szComponent, comp))
829 return ERROR_FUNCTION_FAILED;
830 TRACE("squished (%s)\n", debugstr_w(comp));
832 rc = get_user_sid(&usersid);
833 if (rc != ERROR_SUCCESS || !usersid)
835 ERR("Failed to retrieve user SID: %d\n", rc);
836 return rc;
839 sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
841 LocalFree(usersid);
842 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
845 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
847 UINT rc;
848 WCHAR squished_pc[GUID_SIZE];
849 WCHAR keypath[0x200];
850 LPWSTR usersid;
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));
857 rc = get_user_sid(&usersid);
858 if (rc != ERROR_SUCCESS || !usersid)
860 ERR("Failed to retrieve user SID: %d\n", rc);
861 return rc;
864 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
866 if (create)
867 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
868 else
869 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
871 LocalFree(usersid);
872 return rc;
875 UINT MSIREG_OpenUserDataPatchKey(LPWSTR patch, HKEY *key, BOOL create)
877 UINT rc;
878 WCHAR keypath[0x200];
879 LPWSTR usersid;
881 TRACE("\n");
883 rc = get_user_sid(&usersid);
884 if (rc != ERROR_SUCCESS || !usersid)
886 ERR("Failed to retrieve user SID: %d\n", rc);
887 return rc;
890 sprintfW(keypath, szUserDataPatch_fmt, usersid, patch);
892 if (create)
893 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
894 else
895 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
897 LocalFree(usersid);
898 return rc;
901 UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
903 WCHAR squished_pc[GUID_SIZE];
904 WCHAR keypath[0x200];
906 TRACE("%s\n", debugstr_w(szProduct));
907 if (!squash_guid(szProduct, squished_pc))
908 return ERROR_FUNCTION_FAILED;
909 TRACE("squished (%s)\n", debugstr_w(squished_pc));
911 sprintfW(keypath, szUserDataProd_fmt, localsid, squished_pc);
913 if (create)
914 return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
916 return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
919 static UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, LPCWSTR szUserSID,
920 HKEY *key, BOOL create)
922 UINT rc;
923 WCHAR squished_pc[GUID_SIZE];
924 WCHAR keypath[0x200];
926 TRACE("%s\n", debugstr_w(szProduct));
927 if (!squash_guid(szProduct, squished_pc))
928 return ERROR_FUNCTION_FAILED;
929 TRACE("squished (%s)\n", debugstr_w(squished_pc));
931 sprintfW(keypath, szInstallProperties_fmt, szUserSID, squished_pc);
933 if (create)
934 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
935 else
936 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
938 return rc;
941 UINT MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct, HKEY *key,
942 BOOL create)
944 UINT rc;
945 LPWSTR usersid;
947 rc = get_user_sid(&usersid);
948 if (rc != ERROR_SUCCESS || !usersid)
950 ERR("Failed to retrieve user SID: %d\n", rc);
951 return rc;
954 rc = MSIREG_OpenInstallProps(szProduct, usersid, key, create);
956 LocalFree(usersid);
957 return rc;
960 UINT MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct, HKEY *key,
961 BOOL create)
963 return MSIREG_OpenInstallProps(szProduct, localsid, key, create);
966 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
968 UINT rc;
969 WCHAR squished_pc[GUID_SIZE];
970 WCHAR keypath[0x200];
971 LPWSTR usersid;
973 TRACE("%s\n", debugstr_w(szProduct));
974 if (!squash_guid(szProduct, squished_pc))
975 return ERROR_FUNCTION_FAILED;
976 TRACE("squished (%s)\n", debugstr_w(squished_pc));
978 rc = get_user_sid(&usersid);
979 if (rc != ERROR_SUCCESS || !usersid)
981 ERR("Failed to retrieve user SID: %d\n", rc);
982 return rc;
985 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
987 LocalFree(usersid);
988 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
991 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
993 WCHAR squished_pc[GUID_SIZE];
994 WCHAR keypath[0x200];
996 TRACE("%s\n", debugstr_w(szProduct));
997 if (!squash_guid(szProduct, squished_pc))
998 return ERROR_FUNCTION_FAILED;
999 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1001 sprintfW(keypath, szInstaller_Products_fmt, squished_pc);
1003 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
1006 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
1008 UINT rc;
1009 WCHAR squished_pc[GUID_SIZE];
1010 WCHAR keypath[0x200];
1012 TRACE("%s\n",debugstr_w(szPatch));
1013 if (!squash_guid(szPatch,squished_pc))
1014 return ERROR_FUNCTION_FAILED;
1015 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1017 sprintfW(keypath,szInstaller_Patches_fmt,squished_pc);
1019 if (create)
1020 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
1021 else
1022 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
1024 return rc;
1027 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
1029 UINT rc;
1030 WCHAR squished_pc[GUID_SIZE];
1031 WCHAR keypath[0x200];
1033 TRACE("%s\n",debugstr_w(szUpgradeCode));
1034 if (!squash_guid(szUpgradeCode,squished_pc))
1035 return ERROR_FUNCTION_FAILED;
1036 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1038 sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
1040 if (create)
1041 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
1042 else
1043 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
1045 return rc;
1048 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
1050 UINT rc;
1051 WCHAR squished_pc[GUID_SIZE];
1052 WCHAR keypath[0x200];
1054 TRACE("%s\n",debugstr_w(szUpgradeCode));
1055 if (!squash_guid(szUpgradeCode,squished_pc))
1056 return ERROR_FUNCTION_FAILED;
1057 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1059 sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1061 if (create)
1062 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
1063 else
1064 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
1066 return rc;
1069 UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
1071 WCHAR squished_pc[GUID_SIZE];
1072 WCHAR keypath[0x200];
1074 TRACE("%s\n",debugstr_w(szUpgradeCode));
1075 if (!squash_guid(szUpgradeCode,squished_pc))
1076 return ERROR_FUNCTION_FAILED;
1077 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1079 sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
1081 return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
1084 UINT MSIREG_OpenLocalSystemProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create)
1086 WCHAR squished_pc[GUID_SIZE];
1087 WCHAR keypath[0x200];
1089 TRACE("%s\n", debugstr_w(szProductCode));
1091 if (!squash_guid(szProductCode, squished_pc))
1092 return ERROR_FUNCTION_FAILED;
1094 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1096 sprintfW(keypath, szInstaller_LocalSystemProductCodes_fmt, squished_pc);
1098 if (create)
1099 return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1101 return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1104 UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
1106 WCHAR squished_pc[GUID_SIZE];
1107 WCHAR keypath[0x200];
1109 TRACE("%s\n", debugstr_w(szComponent));
1111 if (!squash_guid(szComponent, squished_pc))
1112 return ERROR_FUNCTION_FAILED;
1114 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1116 sprintfW(keypath, szInstaller_LocalSystemComponent_fmt, squished_pc);
1118 if (create)
1119 return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1121 return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
1124 UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
1126 WCHAR squished_pc[GUID_SIZE];
1127 WCHAR keypath[0x200];
1129 TRACE("%s\n", debugstr_w(szProductCode));
1131 if (!squash_guid(szProductCode, squished_pc))
1132 return ERROR_FUNCTION_FAILED;
1134 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1136 sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc);
1138 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
1141 UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
1143 WCHAR squished_pc[GUID_SIZE];
1144 WCHAR keypath[0x200];
1146 TRACE("%s\n", debugstr_w(szProductCode));
1148 if (!squash_guid(szProductCode, squished_pc))
1149 return ERROR_FUNCTION_FAILED;
1151 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1153 sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc);
1155 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
1158 UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
1160 WCHAR squished_pc[GUID_SIZE];
1161 WCHAR keypath[0x200];
1163 TRACE("%s\n", debugstr_w(szUpgradeCode));
1164 if (!squash_guid(szUpgradeCode, squished_pc))
1165 return ERROR_FUNCTION_FAILED;
1166 TRACE("squished (%s)\n", debugstr_w(squished_pc));
1168 sprintfW(keypath, szInstaller_ClassesUpgrade_fmt, squished_pc);
1170 if (create)
1171 return RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, key);
1173 return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key);
1176 /*************************************************************************
1177 * MsiDecomposeDescriptorW [MSI.@]
1179 * Decomposes an MSI descriptor into product, feature and component parts.
1180 * An MSI descriptor is a string of the form:
1181 * [base 85 guid] [feature code] '>' [base 85 guid]
1183 * PARAMS
1184 * szDescriptor [I] the descriptor to decompose
1185 * szProduct [O] buffer of MAX_FEATURE_CHARS+1 for the product guid
1186 * szFeature [O] buffer of MAX_FEATURE_CHARS+1 for the feature code
1187 * szComponent [O] buffer of MAX_FEATURE_CHARS+1 for the component guid
1188 * pUsed [O] the length of the descriptor
1190 * RETURNS
1191 * ERROR_SUCCESS if everything worked correctly
1192 * ERROR_INVALID_PARAMETER if the descriptor was invalid
1195 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
1196 LPWSTR szFeature, LPWSTR szComponent, LPDWORD pUsed )
1198 UINT r, len;
1199 LPWSTR p;
1200 GUID product, component;
1202 TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
1203 szFeature, szComponent, pUsed);
1205 r = decode_base85_guid( szDescriptor, &product );
1206 if( !r )
1207 return ERROR_INVALID_PARAMETER;
1209 TRACE("product %s\n", debugstr_guid( &product ));
1211 p = strchrW(&szDescriptor[20],'>');
1212 if( !p )
1213 return ERROR_INVALID_PARAMETER;
1215 len = (p - &szDescriptor[20]);
1216 if( len > MAX_FEATURE_CHARS )
1217 return ERROR_INVALID_PARAMETER;
1219 TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
1221 r = decode_base85_guid( p+1, &component );
1222 if( !r )
1223 return ERROR_INVALID_PARAMETER;
1225 TRACE("component %s\n", debugstr_guid( &component ));
1227 if (szProduct)
1228 StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
1229 if (szComponent)
1230 StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
1231 if (szFeature)
1233 memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
1234 szFeature[len] = 0;
1236 len = ( &p[21] - szDescriptor );
1238 TRACE("length = %d\n", len);
1239 *pUsed = len;
1241 return ERROR_SUCCESS;
1244 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
1245 LPSTR szFeature, LPSTR szComponent, LPDWORD pUsed )
1247 WCHAR product[MAX_FEATURE_CHARS+1];
1248 WCHAR feature[MAX_FEATURE_CHARS+1];
1249 WCHAR component[MAX_FEATURE_CHARS+1];
1250 LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
1251 UINT r;
1253 TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
1254 szFeature, szComponent, pUsed);
1256 str = strdupAtoW( szDescriptor );
1257 if( szDescriptor && !str )
1258 return ERROR_OUTOFMEMORY;
1260 if (szProduct)
1261 p = product;
1262 if (szFeature)
1263 f = feature;
1264 if (szComponent)
1265 c = component;
1267 r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
1269 if (r == ERROR_SUCCESS)
1271 WideCharToMultiByte( CP_ACP, 0, p, -1,
1272 szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
1273 WideCharToMultiByte( CP_ACP, 0, f, -1,
1274 szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
1275 WideCharToMultiByte( CP_ACP, 0, c, -1,
1276 szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
1279 msi_free( str );
1281 return r;
1284 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
1286 DWORD r;
1287 WCHAR szwGuid[GUID_SIZE];
1289 TRACE("%d %p\n", index, lpguid);
1291 if (NULL == lpguid)
1292 return ERROR_INVALID_PARAMETER;
1293 r = MsiEnumProductsW(index, szwGuid);
1294 if( r == ERROR_SUCCESS )
1295 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1297 return r;
1300 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
1302 HKEY hkeyProducts = 0;
1303 DWORD r;
1304 WCHAR szKeyName[SQUISH_GUID_SIZE];
1306 TRACE("%d %p\n", index, lpguid);
1308 if (NULL == lpguid)
1309 return ERROR_INVALID_PARAMETER;
1311 r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
1312 if( r != ERROR_SUCCESS )
1313 return ERROR_NO_MORE_ITEMS;
1315 r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
1316 if( r == ERROR_SUCCESS )
1317 unsquash_guid(szKeyName, lpguid);
1318 RegCloseKey(hkeyProducts);
1320 return r;
1323 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
1324 LPSTR szFeature, LPSTR szParent)
1326 DWORD r;
1327 WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
1328 LPWSTR szwProduct = NULL;
1330 TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
1332 if( szProduct )
1334 szwProduct = strdupAtoW( szProduct );
1335 if( !szwProduct )
1336 return ERROR_OUTOFMEMORY;
1339 r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
1340 if( r == ERROR_SUCCESS )
1342 WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
1343 szFeature, GUID_SIZE, NULL, NULL);
1344 WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
1345 szParent, GUID_SIZE, NULL, NULL);
1348 msi_free( szwProduct);
1350 return r;
1353 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
1354 LPWSTR szFeature, LPWSTR szParent)
1356 HKEY hkeyProduct = 0;
1357 DWORD r, sz;
1359 TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
1361 if( !szProduct )
1362 return ERROR_INVALID_PARAMETER;
1364 r = MSIREG_OpenInstallerFeaturesKey(szProduct,&hkeyProduct,FALSE);
1365 if( r != ERROR_SUCCESS )
1366 return ERROR_NO_MORE_ITEMS;
1368 sz = GUID_SIZE;
1369 r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1370 RegCloseKey(hkeyProduct);
1372 return r;
1375 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1377 DWORD r;
1378 WCHAR szwGuid[GUID_SIZE];
1380 TRACE("%d %p\n", index, lpguid);
1382 r = MsiEnumComponentsW(index, szwGuid);
1383 if( r == ERROR_SUCCESS )
1384 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1386 return r;
1389 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1391 HKEY hkeyComponents = 0;
1392 DWORD r;
1393 WCHAR szKeyName[SQUISH_GUID_SIZE];
1395 TRACE("%d %p\n", index, lpguid);
1397 r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Components, &hkeyComponents);
1398 if( r != ERROR_SUCCESS )
1399 return ERROR_NO_MORE_ITEMS;
1401 r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
1402 if( r == ERROR_SUCCESS )
1403 unsquash_guid(szKeyName, lpguid);
1404 RegCloseKey(hkeyComponents);
1406 return r;
1409 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1411 DWORD r;
1412 WCHAR szwProduct[GUID_SIZE];
1413 LPWSTR szwComponent = NULL;
1415 TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
1417 if ( !szProduct )
1418 return ERROR_INVALID_PARAMETER;
1420 if( szComponent )
1422 szwComponent = strdupAtoW( szComponent );
1423 if( !szwComponent )
1424 return ERROR_OUTOFMEMORY;
1427 r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1428 if( r == ERROR_SUCCESS )
1430 WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1431 szProduct, GUID_SIZE, NULL, NULL);
1434 msi_free( szwComponent);
1436 return r;
1439 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1441 HKEY hkeyComp = 0;
1442 DWORD r, sz;
1443 WCHAR szValName[SQUISH_GUID_SIZE];
1445 TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
1447 if (!szComponent || !*szComponent || !szProduct)
1448 return ERROR_INVALID_PARAMETER;
1450 if (MSIREG_OpenUserDataComponentKey(szComponent, &hkeyComp, FALSE) != ERROR_SUCCESS &&
1451 MSIREG_OpenLocalSystemComponentKey(szComponent, &hkeyComp, FALSE) != ERROR_SUCCESS)
1452 return ERROR_UNKNOWN_COMPONENT;
1454 /* see if there are any products at all */
1455 sz = SQUISH_GUID_SIZE;
1456 r = RegEnumValueW(hkeyComp, 0, szValName, &sz, NULL, NULL, NULL, NULL);
1457 if (r != ERROR_SUCCESS)
1459 RegCloseKey(hkeyComp);
1461 if (index != 0)
1462 return ERROR_INVALID_PARAMETER;
1464 return ERROR_UNKNOWN_COMPONENT;
1467 sz = SQUISH_GUID_SIZE;
1468 r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1469 if( r == ERROR_SUCCESS )
1470 unsquash_guid(szValName, szProduct);
1472 RegCloseKey(hkeyComp);
1474 return r;
1477 static UINT MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
1478 awstring *lpQualBuf, LPDWORD pcchQual,
1479 awstring *lpAppBuf, LPDWORD pcchAppBuf )
1481 DWORD name_sz, val_sz, name_max, val_max, type, ofs;
1482 LPWSTR name = NULL, val = NULL;
1483 UINT r, r2;
1484 HKEY key;
1486 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1487 lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
1489 if (!szComponent)
1490 return ERROR_INVALID_PARAMETER;
1492 r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1493 if (r != ERROR_SUCCESS)
1494 return ERROR_UNKNOWN_COMPONENT;
1496 /* figure out how big the name is we want to return */
1497 name_max = 0x10;
1498 r = ERROR_OUTOFMEMORY;
1499 name = msi_alloc( name_max * sizeof(WCHAR) );
1500 if (!name)
1501 goto end;
1503 val_max = 0x10;
1504 r = ERROR_OUTOFMEMORY;
1505 val = msi_alloc( val_max );
1506 if (!val)
1507 goto end;
1509 /* loop until we allocate enough memory */
1510 while (1)
1512 name_sz = name_max;
1513 val_sz = val_max;
1514 r = RegEnumValueW( key, iIndex, name, &name_sz,
1515 NULL, &type, (LPBYTE)val, &val_sz );
1516 if (r == ERROR_SUCCESS)
1517 break;
1518 if (r != ERROR_MORE_DATA)
1519 goto end;
1521 if (type != REG_MULTI_SZ)
1523 ERR("component data has wrong type (%d)\n", type);
1524 goto end;
1527 r = ERROR_OUTOFMEMORY;
1528 if ((name_sz+1) >= name_max)
1530 name_max *= 2;
1531 msi_free( name );
1532 name = msi_alloc( name_max * sizeof (WCHAR) );
1533 if (!name)
1534 goto end;
1535 continue;
1537 if (val_sz > val_max)
1539 val_max = val_sz + sizeof (WCHAR);
1540 msi_free( val );
1541 val = msi_alloc( val_max * sizeof (WCHAR) );
1542 if (!val)
1543 goto end;
1544 continue;
1546 ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
1547 goto end;
1550 ofs = 0;
1551 r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1552 if (r != ERROR_SUCCESS)
1553 goto end;
1555 TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1557 r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
1558 r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
1560 if (r2 != ERROR_SUCCESS)
1561 r = r2;
1563 end:
1564 msi_free(val);
1565 msi_free(name);
1566 RegCloseKey(key);
1568 return r;
1571 /*************************************************************************
1572 * MsiEnumComponentQualifiersA [MSI.@]
1574 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
1575 LPSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1576 LPSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1578 awstring qual, appdata;
1579 LPWSTR comp;
1580 UINT r;
1582 TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
1583 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1584 pcchApplicationDataBuf);
1586 comp = strdupAtoW( szComponent );
1587 if (szComponent && !comp)
1588 return ERROR_OUTOFMEMORY;
1590 qual.unicode = FALSE;
1591 qual.str.a = lpQualifierBuf;
1593 appdata.unicode = FALSE;
1594 appdata.str.a = lpApplicationDataBuf;
1596 r = MSI_EnumComponentQualifiers( comp, iIndex,
1597 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1598 msi_free( comp );
1599 return r;
1602 /*************************************************************************
1603 * MsiEnumComponentQualifiersW [MSI.@]
1605 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
1606 LPWSTR lpQualifierBuf, LPDWORD pcchQualifierBuf,
1607 LPWSTR lpApplicationDataBuf, LPDWORD pcchApplicationDataBuf )
1609 awstring qual, appdata;
1611 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1612 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1613 pcchApplicationDataBuf);
1615 qual.unicode = TRUE;
1616 qual.str.w = lpQualifierBuf;
1618 appdata.unicode = TRUE;
1619 appdata.str.w = lpApplicationDataBuf;
1621 return MSI_EnumComponentQualifiers( szComponent, iIndex,
1622 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1625 /*************************************************************************
1626 * MsiEnumRelatedProductsW [MSI.@]
1629 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
1630 DWORD iProductIndex, LPWSTR lpProductBuf)
1632 UINT r;
1633 HKEY hkey;
1634 DWORD dwSize = SQUISH_GUID_SIZE;
1635 WCHAR szKeyName[SQUISH_GUID_SIZE];
1637 TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
1638 iProductIndex, lpProductBuf);
1640 if (NULL == szUpgradeCode)
1641 return ERROR_INVALID_PARAMETER;
1642 if (NULL == lpProductBuf)
1643 return ERROR_INVALID_PARAMETER;
1645 r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1646 if (r != ERROR_SUCCESS)
1647 return ERROR_NO_MORE_ITEMS;
1649 r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1650 if( r == ERROR_SUCCESS )
1651 unsquash_guid(szKeyName, lpProductBuf);
1652 RegCloseKey(hkey);
1654 return r;
1657 /*************************************************************************
1658 * MsiEnumRelatedProductsA [MSI.@]
1661 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
1662 DWORD iProductIndex, LPSTR lpProductBuf)
1664 LPWSTR szwUpgradeCode = NULL;
1665 WCHAR productW[GUID_SIZE];
1666 UINT r;
1668 TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
1669 iProductIndex, lpProductBuf);
1671 if (szUpgradeCode)
1673 szwUpgradeCode = strdupAtoW( szUpgradeCode );
1674 if( !szwUpgradeCode )
1675 return ERROR_OUTOFMEMORY;
1678 r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1679 iProductIndex, productW );
1680 if (r == ERROR_SUCCESS)
1682 WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1683 lpProductBuf, GUID_SIZE, NULL, NULL );
1685 msi_free( szwUpgradeCode);
1686 return r;
1689 /***********************************************************************
1690 * MsiEnumPatchesExA [MSI.@]
1692 UINT WINAPI MsiEnumPatchesExA(LPCSTR szProductCode, LPCSTR szUserSid,
1693 DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPSTR szPatchCode,
1694 LPSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
1695 LPSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
1697 LPWSTR prodcode = NULL;
1698 LPWSTR usersid = NULL;
1699 LPWSTR targsid = NULL;
1700 WCHAR patch[GUID_SIZE];
1701 WCHAR targprod[GUID_SIZE];
1702 DWORD len;
1703 UINT r;
1705 TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
1706 debugstr_a(szProductCode), debugstr_a(szUserSid), dwContext, dwFilter,
1707 dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
1708 szTargetUserSid, pcchTargetUserSid);
1710 if (szTargetUserSid && !pcchTargetUserSid)
1711 return ERROR_INVALID_PARAMETER;
1713 if (szProductCode) prodcode = strdupAtoW(szProductCode);
1714 if (szUserSid) usersid = strdupAtoW(szUserSid);
1716 r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1717 patch, targprod, pdwTargetProductContext,
1718 NULL, &len);
1719 if (r != ERROR_SUCCESS)
1720 goto done;
1722 WideCharToMultiByte(CP_ACP, 0, patch, -1, szPatchCode,
1723 GUID_SIZE, NULL, NULL);
1724 WideCharToMultiByte(CP_ACP, 0, targprod, -1, szTargetProductCode,
1725 GUID_SIZE, NULL, NULL);
1727 if (!szTargetUserSid)
1729 if (pcchTargetUserSid)
1730 *pcchTargetUserSid = len;
1732 goto done;
1735 targsid = msi_alloc(++len * sizeof(WCHAR));
1736 if (!targsid)
1738 r = ERROR_OUTOFMEMORY;
1739 goto done;
1742 r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1743 patch, targprod, pdwTargetProductContext,
1744 targsid, &len);
1745 if (r != ERROR_SUCCESS || !szTargetUserSid)
1746 goto done;
1748 WideCharToMultiByte(CP_ACP, 0, targsid, -1, szTargetUserSid,
1749 *pcchTargetUserSid, NULL, NULL);
1751 len = lstrlenW(targsid);
1752 if (*pcchTargetUserSid < len + 1)
1754 r = ERROR_MORE_DATA;
1755 *pcchTargetUserSid = len * sizeof(WCHAR);
1757 else
1758 *pcchTargetUserSid = len;
1760 done:
1761 msi_free(prodcode);
1762 msi_free(usersid);
1763 msi_free(targsid);
1765 return r;
1768 static UINT msi_get_patch_state(LPCWSTR prodcode, LPCWSTR usersid,
1769 LPWSTR patch, MSIPATCHSTATE *state)
1771 DWORD type, val, size;
1772 HKEY prod, hkey = 0;
1773 HKEY udpatch = 0;
1774 LONG res;
1775 UINT r = ERROR_NO_MORE_ITEMS;
1777 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1778 static const WCHAR szState[] = {'S','t','a','t','e',0};
1780 *state = MSIPATCHSTATE_INVALID;
1782 /* FIXME: usersid might not be current user */
1783 r = MSIREG_OpenUserDataProductKey(prodcode, &prod, FALSE);
1784 if (r != ERROR_SUCCESS)
1785 return ERROR_NO_MORE_ITEMS;
1787 res = RegOpenKeyExW(prod, szPatches, 0, KEY_READ, &hkey);
1788 if (res != ERROR_SUCCESS)
1789 goto done;
1791 res = RegOpenKeyExW(hkey, patch, 0, KEY_READ, &udpatch);
1792 if (res != ERROR_SUCCESS)
1793 goto done;
1795 size = sizeof(DWORD);
1796 res = RegGetValueW(udpatch, NULL, szState, RRF_RT_DWORD, &type, &val, &size);
1797 if (res != ERROR_SUCCESS ||
1798 val < MSIPATCHSTATE_APPLIED || val > MSIPATCHSTATE_REGISTERED)
1800 r = ERROR_BAD_CONFIGURATION;
1801 goto done;
1804 *state = val;
1805 r = ERROR_SUCCESS;
1807 done:
1808 RegCloseKey(udpatch);
1809 RegCloseKey(hkey);
1810 RegCloseKey(prod);
1812 return r;
1815 static UINT msi_check_product_patches(LPCWSTR prodcode, LPCWSTR usersid,
1816 MSIINSTALLCONTEXT context, DWORD filter, DWORD index, DWORD *idx,
1817 LPWSTR patch, LPWSTR targetprod, MSIINSTALLCONTEXT *targetctx,
1818 LPWSTR targetsid, DWORD *sidsize)
1820 MSIPATCHSTATE state;
1821 LPWSTR ptr, patches = NULL;
1822 HKEY prod, patchkey = 0;
1823 HKEY localprod = 0, localpatch = 0;
1824 DWORD type, size;
1825 LONG res;
1826 UINT temp, r = ERROR_NO_MORE_ITEMS;
1828 static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0};
1829 static const WCHAR szState[] = {'S','t','a','t','e',0};
1830 static const WCHAR szEmpty[] = {0};
1832 if (MSIREG_OpenProductKey(prodcode, context, &prod, FALSE) != ERROR_SUCCESS)
1833 return ERROR_NO_MORE_ITEMS;
1835 size = 0;
1836 res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type, NULL,
1837 &size);
1838 if (res != ERROR_SUCCESS)
1839 goto done;
1841 if (type != REG_MULTI_SZ)
1843 r = ERROR_BAD_CONFIGURATION;
1844 goto done;
1847 patches = msi_alloc(size);
1848 if (!patches)
1850 r = ERROR_OUTOFMEMORY;
1851 goto done;
1854 res = RegGetValueW(prod, szPatches, szPatches, RRF_RT_ANY, &type,
1855 patches, &size);
1856 if (res != ERROR_SUCCESS)
1857 goto done;
1859 ptr = patches;
1860 for (ptr = patches; *ptr && r == ERROR_NO_MORE_ITEMS; ptr += lstrlenW(ptr))
1862 if (!unsquash_guid(ptr, patch))
1864 r = ERROR_BAD_CONFIGURATION;
1865 goto done;
1868 size = 0;
1869 res = RegGetValueW(prod, szPatches, ptr, RRF_RT_REG_SZ,
1870 &type, NULL, &size);
1871 if (res != ERROR_SUCCESS)
1872 continue;
1874 if (context == MSIINSTALLCONTEXT_USERMANAGED)
1876 if (!(filter & MSIPATCHSTATE_APPLIED))
1878 temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
1879 if (temp == ERROR_BAD_CONFIGURATION)
1881 r = ERROR_BAD_CONFIGURATION;
1882 goto done;
1885 if (temp != ERROR_SUCCESS || !(filter & state))
1886 continue;
1889 else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
1891 if (!(filter & MSIPATCHSTATE_APPLIED))
1893 temp = msi_get_patch_state(prodcode, usersid, ptr, &state);
1894 if (temp == ERROR_BAD_CONFIGURATION)
1896 r = ERROR_BAD_CONFIGURATION;
1897 goto done;
1900 if (temp != ERROR_SUCCESS || !(filter & state))
1901 continue;
1903 else
1905 temp = MSIREG_OpenUserDataPatchKey(ptr, &patchkey, FALSE);
1906 RegCloseKey(patchkey);
1907 if (temp != ERROR_SUCCESS)
1908 continue;
1911 else if (context == MSIINSTALLCONTEXT_MACHINE)
1913 usersid = szEmpty;
1915 if (MSIREG_OpenLocalUserDataProductKey(prodcode, &localprod, FALSE) == ERROR_SUCCESS &&
1916 RegOpenKeyExW(localprod, szPatches, 0, KEY_READ, &localpatch) == ERROR_SUCCESS &&
1917 RegOpenKeyExW(localpatch, ptr, 0, KEY_READ, &patchkey) == ERROR_SUCCESS)
1919 res = RegGetValueW(patchkey, NULL, szState, RRF_RT_REG_DWORD,
1920 &type, &state, &size);
1922 if (!(filter & state))
1923 res = ERROR_NO_MORE_ITEMS;
1925 RegCloseKey(patchkey);
1928 RegCloseKey(localpatch);
1929 RegCloseKey(localprod);
1931 if (res != ERROR_SUCCESS)
1932 continue;
1935 if (*idx < index)
1937 (*idx)++;
1938 continue;
1941 r = ERROR_SUCCESS;
1942 lstrcpyW(targetprod, prodcode);
1944 if (targetctx)
1945 *targetctx = context;
1947 if (targetsid)
1949 lstrcpynW(targetsid, usersid, *sidsize);
1950 if (lstrlenW(usersid) >= *sidsize)
1951 r = ERROR_MORE_DATA;
1954 if (sidsize)
1956 *sidsize = lstrlenW(usersid);
1957 if (!targetsid)
1958 *sidsize *= sizeof(WCHAR);
1962 done:
1963 RegCloseKey(prod);
1964 msi_free(patches);
1966 return r;
1969 /***********************************************************************
1970 * MsiEnumPatchesExW [MSI.@]
1972 UINT WINAPI MsiEnumPatchesExW(LPCWSTR szProductCode, LPCWSTR szUserSid,
1973 DWORD dwContext, DWORD dwFilter, DWORD dwIndex, LPWSTR szPatchCode,
1974 LPWSTR szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext,
1975 LPWSTR szTargetUserSid, LPDWORD pcchTargetUserSid)
1977 WCHAR squished_pc[GUID_SIZE];
1978 DWORD idx = 0;
1979 UINT r;
1981 static int last_index = 0;
1983 TRACE("(%s, %s, %d, %d, %d, %p, %p, %p, %p, %p)\n",
1984 debugstr_w(szProductCode), debugstr_w(szUserSid), dwContext, dwFilter,
1985 dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext,
1986 szTargetUserSid, pcchTargetUserSid);
1988 if (!szProductCode || !squash_guid(szProductCode, squished_pc))
1989 return ERROR_INVALID_PARAMETER;
1991 if (!lstrcmpW(szUserSid, localsid))
1992 return ERROR_INVALID_PARAMETER;
1994 if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
1995 return ERROR_INVALID_PARAMETER;
1997 if (dwContext <= MSIINSTALLCONTEXT_NONE ||
1998 dwContext > MSIINSTALLCONTEXT_ALL)
1999 return ERROR_INVALID_PARAMETER;
2001 if (dwFilter <= MSIPATCHSTATE_INVALID || dwFilter > MSIPATCHSTATE_ALL)
2002 return ERROR_INVALID_PARAMETER;
2004 if (dwIndex && dwIndex - last_index != 1)
2005 return ERROR_INVALID_PARAMETER;
2007 if (dwIndex == 0)
2008 last_index = 0;
2010 if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
2012 r = msi_check_product_patches(szProductCode, szUserSid,
2013 MSIINSTALLCONTEXT_USERMANAGED, dwFilter,
2014 dwIndex, &idx, szPatchCode,
2015 szTargetProductCode,
2016 pdwTargetProductContext,
2017 szTargetUserSid, pcchTargetUserSid);
2018 if (r != ERROR_NO_MORE_ITEMS)
2019 goto done;
2022 if (dwContext & MSIINSTALLCONTEXT_USERUNMANAGED)
2024 r = msi_check_product_patches(szProductCode, szUserSid,
2025 MSIINSTALLCONTEXT_USERUNMANAGED, dwFilter,
2026 dwIndex, &idx, szPatchCode,
2027 szTargetProductCode,
2028 pdwTargetProductContext,
2029 szTargetUserSid, pcchTargetUserSid);
2030 if (r != ERROR_NO_MORE_ITEMS)
2031 goto done;
2034 if (dwContext & MSIINSTALLCONTEXT_MACHINE)
2036 r = msi_check_product_patches(szProductCode, szUserSid,
2037 MSIINSTALLCONTEXT_MACHINE, dwFilter,
2038 dwIndex, &idx, szPatchCode,
2039 szTargetProductCode,
2040 pdwTargetProductContext,
2041 szTargetUserSid, pcchTargetUserSid);
2042 if (r != ERROR_NO_MORE_ITEMS)
2043 goto done;
2046 done:
2047 if (r == ERROR_SUCCESS)
2048 last_index = dwIndex;
2050 return r;
2053 /***********************************************************************
2054 * MsiEnumPatchesA [MSI.@]
2056 UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
2057 LPSTR lpPatchBuf, LPSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
2059 FIXME("%s %d %p %p %p\n", debugstr_a(szProduct),
2060 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
2061 return ERROR_NO_MORE_ITEMS;
2064 /***********************************************************************
2065 * MsiEnumPatchesW [MSI.@]
2067 UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
2068 LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, LPDWORD pcchTransformsBuf)
2070 FIXME("%s %d %p %p %p\n", debugstr_w(szProduct),
2071 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
2072 return ERROR_NO_MORE_ITEMS;
2075 UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
2076 DWORD dwContext, DWORD dwIndex, CHAR szInstalledProductCode[39],
2077 MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
2079 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
2080 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
2081 szSid, pcchSid);
2082 return ERROR_NO_MORE_ITEMS;
2085 UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
2086 DWORD dwContext, DWORD dwIndex, WCHAR szInstalledProductCode[39],
2087 MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
2089 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
2090 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
2091 szSid, pcchSid);
2092 return ERROR_NO_MORE_ITEMS;