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
25 #define NONAMELESSUNION
32 #include "wine/debug.h"
36 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
45 * This module will be all the helper functions for registry access by the
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
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','\\',
247 static const WCHAR localsid
[] = {'S','-','1','-','5','-','1','8',0};
249 BOOL
unsquash_guid(LPCWSTR in
, LPWSTR out
)
253 if (lstrlenW(in
) != 32)
268 out
[n
++] = in
[17+i
*2];
269 out
[n
++] = in
[16+i
*2];
274 out
[n
++] = in
[17+i
*2];
275 out
[n
++] = in
[16+i
*2];
282 BOOL
squash_guid(LPCWSTR in
, LPWSTR out
)
289 if (FAILED(CLSIDFromString((LPOLESTR
)in
, &guid
)))
303 out
[17+i
*2] = in
[n
++];
304 out
[16+i
*2] = in
[n
++];
309 out
[17+i
*2] = in
[n
++];
310 out
[16+i
*2] = in
[n
++];
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"
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
;
348 for( i
=0; i
<20; i
++ )
355 val
+= table_dec85
[str
[i
]] * base
;
358 if( table_dec85
[str
[i
]] == 0xff )
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
;
381 *str
++ = table_enc85
[x
%85];
383 *str
++ = table_enc85
[x
%85];
385 *str
++ = table_enc85
[x
%85];
387 *str
++ = table_enc85
[x
%85];
389 *str
++ = table_enc85
[x
%85];
396 DWORD
msi_version_str_to_dword(LPCWSTR p
)
398 DWORD major
, minor
= 0, build
= 0, version
= 0;
409 p
= strchrW(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);
422 (version
&0xff000000)>>24,
423 (version
&0x00ff0000)>>16,
428 LONG
msi_reg_set_val_str( HKEY hkey
, LPCWSTR name
, LPCWSTR value
)
430 static const WCHAR emptyW
[] = {0};
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
)
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
)
455 r
= RegCreateKeyW( hkey
, path
, &hsubkey
);
456 if (r
!= ERROR_SUCCESS
)
458 r
= msi_reg_set_val_str( hsubkey
, name
, val
);
459 RegCloseKey( hsubkey
);
463 LPWSTR
msi_reg_get_val_str( HKEY hkey
, LPCWSTR name
)
469 r
= RegQueryValueExW(hkey
, name
, NULL
, NULL
, NULL
, &len
);
470 if (r
!= ERROR_SUCCESS
)
473 len
+= sizeof (WCHAR
);
474 val
= msi_alloc( len
);
478 RegQueryValueExW(hkey
, name
, NULL
, NULL
, (LPBYTE
) val
, &len
);
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
)
496 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &token
))
497 return ERROR_FUNCTION_FAILED
;
500 if (!GetTokenInformation(token
, TokenUser
, (void *)buf
, size
, &size
)) {
502 return ERROR_FUNCTION_FAILED
;
505 user
= (PTOKEN_USER
)buf
;
506 if (!ConvertSidToStringSidW(user
->User
.Sid
, usersid
)) {
508 return ERROR_FUNCTION_FAILED
;
511 return ERROR_SUCCESS
;
514 UINT
MSIREG_OpenUninstallKey(LPCWSTR szProduct
, HKEY
* key
, BOOL create
)
517 WCHAR keypath
[0x200];
518 TRACE("%s\n",debugstr_w(szProduct
));
520 sprintfW(keypath
,szUninstall_fmt
,szProduct
);
523 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
525 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
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
)
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
);
567 r
= get_user_sid(&usersid
);
568 if (r
!= ERROR_SUCCESS
|| !usersid
)
570 ERR("Failed to retrieve user SID: %d\n", r
);
574 sprintfW(keypath
, szInstaller_LocalManagedProd_fmt
, usersid
, squished_pc
);
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
)
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
);
613 rc
= RegCreateKeyW(HKEY_CURRENT_USER
,keypath
,key
);
615 rc
= RegOpenKeyW(HKEY_CURRENT_USER
,keypath
,key
);
620 UINT
MSIREG_OpenFeaturesKey(LPCWSTR szProduct
, MSIINSTALLCONTEXT context
,
621 HKEY
*key
, BOOL create
)
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
);
647 r
= get_user_sid(&usersid
);
648 if (r
!= ERROR_SUCCESS
|| !usersid
)
650 ERR("Failed to retrieve user SID: %d\n", r
);
654 sprintfW(keypath
, szInstaller_LocalManagedFeat_fmt
, usersid
, squished_pc
);
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
)
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
);
692 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
694 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
699 UINT
MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct
, MSIINSTALLCONTEXT context
,
700 HKEY
*key
, BOOL create
)
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
);
720 r
= get_user_sid(&usersid
);
721 if (r
!= ERROR_SUCCESS
|| !usersid
)
723 ERR("Failed to retrieve user SID: %d\n", r
);
727 sprintfW(keypath
, szUserDataFeatures_fmt
, usersid
, squished_pc
);
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
)
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
);
751 rc
= RegCreateKeyW(HKEY_CURRENT_USER
,keypath
,key
);
753 rc
= RegOpenKeyW(HKEY_CURRENT_USER
,keypath
,key
);
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
);
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
)
793 WCHAR comp
[GUID_SIZE
];
794 WCHAR keypath
[0x200];
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
);
809 sprintfW(keypath
, szUserDataComp_fmt
, usersid
, comp
);
812 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
814 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
820 UINT
MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent
)
823 WCHAR comp
[GUID_SIZE
];
824 WCHAR keypath
[0x200];
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
);
839 sprintfW(keypath
, szUserDataComp_fmt
, usersid
, comp
);
842 return RegDeleteTreeW(HKEY_LOCAL_MACHINE
, keypath
);
845 UINT
MSIREG_OpenUserDataProductKey(LPCWSTR szProduct
, HKEY
*key
, BOOL create
)
848 WCHAR squished_pc
[GUID_SIZE
];
849 WCHAR keypath
[0x200];
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
);
864 sprintfW(keypath
, szUserDataProd_fmt
, usersid
, squished_pc
);
867 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
869 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
875 UINT
MSIREG_OpenUserDataPatchKey(LPWSTR patch
, HKEY
*key
, BOOL create
)
878 WCHAR keypath
[0x200];
883 rc
= get_user_sid(&usersid
);
884 if (rc
!= ERROR_SUCCESS
|| !usersid
)
886 ERR("Failed to retrieve user SID: %d\n", rc
);
890 sprintfW(keypath
, szUserDataPatch_fmt
, usersid
, patch
);
893 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
895 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
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
);
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
)
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
);
934 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
936 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, keypath
, key
);
941 UINT
MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct
, HKEY
*key
,
947 rc
= get_user_sid(&usersid
);
948 if (rc
!= ERROR_SUCCESS
|| !usersid
)
950 ERR("Failed to retrieve user SID: %d\n", rc
);
954 rc
= MSIREG_OpenInstallProps(szProduct
, usersid
, key
, create
);
960 UINT
MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct
, HKEY
*key
,
963 return MSIREG_OpenInstallProps(szProduct
, localsid
, key
, create
);
966 UINT
MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct
)
969 WCHAR squished_pc
[GUID_SIZE
];
970 WCHAR keypath
[0x200];
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
);
985 sprintfW(keypath
, szUserDataProd_fmt
, usersid
, squished_pc
);
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
)
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
);
1020 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
1022 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
1027 UINT
MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode
, HKEY
* key
, BOOL create
)
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
);
1041 rc
= RegCreateKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
1043 rc
= RegOpenKeyW(HKEY_LOCAL_MACHINE
,keypath
,key
);
1048 UINT
MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode
, HKEY
* key
, BOOL create
)
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
);
1062 rc
= RegCreateKeyW(HKEY_CURRENT_USER
,keypath
,key
);
1064 rc
= RegOpenKeyW(HKEY_CURRENT_USER
,keypath
,key
);
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
);
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
);
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
);
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]
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
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
)
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
);
1207 return ERROR_INVALID_PARAMETER
;
1209 TRACE("product %s\n", debugstr_guid( &product
));
1211 p
= strchrW(&szDescriptor
[20],'>');
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
);
1223 return ERROR_INVALID_PARAMETER
;
1225 TRACE("component %s\n", debugstr_guid( &component
));
1228 StringFromGUID2( &product
, szProduct
, MAX_FEATURE_CHARS
+1 );
1230 StringFromGUID2( &component
, szComponent
, MAX_FEATURE_CHARS
+1 );
1233 memcpy( szFeature
, &szDescriptor
[20], len
*sizeof(WCHAR
) );
1236 len
= ( &p
[21] - szDescriptor
);
1238 TRACE("length = %d\n", 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
;
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
;
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
);
1284 UINT WINAPI
MsiEnumProductsA(DWORD index
, LPSTR lpguid
)
1287 WCHAR szwGuid
[GUID_SIZE
];
1289 TRACE("%d %p\n", index
, 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
);
1300 UINT WINAPI
MsiEnumProductsW(DWORD index
, LPWSTR lpguid
)
1302 HKEY hkeyProducts
= 0;
1304 WCHAR szKeyName
[SQUISH_GUID_SIZE
];
1306 TRACE("%d %p\n", index
, 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
);
1323 UINT WINAPI
MsiEnumFeaturesA(LPCSTR szProduct
, DWORD index
,
1324 LPSTR szFeature
, LPSTR szParent
)
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
);
1334 szwProduct
= strdupAtoW( szProduct
);
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
);
1353 UINT WINAPI
MsiEnumFeaturesW(LPCWSTR szProduct
, DWORD index
,
1354 LPWSTR szFeature
, LPWSTR szParent
)
1356 HKEY hkeyProduct
= 0;
1359 TRACE("%s %d %p %p\n", debugstr_w(szProduct
), index
, szFeature
, szParent
);
1362 return ERROR_INVALID_PARAMETER
;
1364 r
= MSIREG_OpenInstallerFeaturesKey(szProduct
,&hkeyProduct
,FALSE
);
1365 if( r
!= ERROR_SUCCESS
)
1366 return ERROR_NO_MORE_ITEMS
;
1369 r
= RegEnumValueW(hkeyProduct
, index
, szFeature
, &sz
, NULL
, NULL
, NULL
, NULL
);
1370 RegCloseKey(hkeyProduct
);
1375 UINT WINAPI
MsiEnumComponentsA(DWORD index
, LPSTR lpguid
)
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
);
1389 UINT WINAPI
MsiEnumComponentsW(DWORD index
, LPWSTR lpguid
)
1391 HKEY hkeyComponents
= 0;
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
);
1409 UINT WINAPI
MsiEnumClientsA(LPCSTR szComponent
, DWORD index
, LPSTR szProduct
)
1412 WCHAR szwProduct
[GUID_SIZE
];
1413 LPWSTR szwComponent
= NULL
;
1415 TRACE("%s %d %p\n", debugstr_a(szComponent
), index
, szProduct
);
1418 return ERROR_INVALID_PARAMETER
;
1422 szwComponent
= strdupAtoW( szComponent
);
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
);
1439 UINT WINAPI
MsiEnumClientsW(LPCWSTR szComponent
, DWORD index
, LPWSTR szProduct
)
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
);
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
);
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
;
1486 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent
), iIndex
,
1487 lpQualBuf
, pcchQual
, lpAppBuf
, pcchAppBuf
);
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 */
1498 r
= ERROR_OUTOFMEMORY
;
1499 name
= msi_alloc( name_max
* sizeof(WCHAR
) );
1504 r
= ERROR_OUTOFMEMORY
;
1505 val
= msi_alloc( val_max
);
1509 /* loop until we allocate enough memory */
1514 r
= RegEnumValueW( key
, iIndex
, name
, &name_sz
,
1515 NULL
, &type
, (LPBYTE
)val
, &val_sz
);
1516 if (r
== ERROR_SUCCESS
)
1518 if (r
!= ERROR_MORE_DATA
)
1521 if (type
!= REG_MULTI_SZ
)
1523 ERR("component data has wrong type (%d)\n", type
);
1527 r
= ERROR_OUTOFMEMORY
;
1528 if ((name_sz
+1) >= name_max
)
1532 name
= msi_alloc( name_max
* sizeof (WCHAR
) );
1537 if (val_sz
> val_max
)
1539 val_max
= val_sz
+ sizeof (WCHAR
);
1541 val
= msi_alloc( val_max
* sizeof (WCHAR
) );
1546 ERR("should be enough data, but isn't %d %d\n", name_sz
, val_sz
);
1551 r
= MsiDecomposeDescriptorW( val
, NULL
, NULL
, NULL
, &ofs
);
1552 if (r
!= ERROR_SUCCESS
)
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
)
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
;
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
);
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
)
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
);
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
];
1668 TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode
), dwReserved
,
1669 iProductIndex
, lpProductBuf
);
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
);
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
];
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
,
1719 if (r
!= ERROR_SUCCESS
)
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
;
1735 targsid
= msi_alloc(++len
* sizeof(WCHAR
));
1738 r
= ERROR_OUTOFMEMORY
;
1742 r
= MsiEnumPatchesExW(prodcode
, usersid
, dwContext
, dwFilter
, dwIndex
,
1743 patch
, targprod
, pdwTargetProductContext
,
1745 if (r
!= ERROR_SUCCESS
|| !szTargetUserSid
)
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
);
1758 *pcchTargetUserSid
= len
;
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;
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
)
1791 res
= RegOpenKeyExW(hkey
, patch
, 0, KEY_READ
, &udpatch
);
1792 if (res
!= ERROR_SUCCESS
)
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
;
1808 RegCloseKey(udpatch
);
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;
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
;
1836 res
= RegGetValueW(prod
, szPatches
, szPatches
, RRF_RT_ANY
, &type
, NULL
,
1838 if (res
!= ERROR_SUCCESS
)
1841 if (type
!= REG_MULTI_SZ
)
1843 r
= ERROR_BAD_CONFIGURATION
;
1847 patches
= msi_alloc(size
);
1850 r
= ERROR_OUTOFMEMORY
;
1854 res
= RegGetValueW(prod
, szPatches
, szPatches
, RRF_RT_ANY
, &type
,
1856 if (res
!= ERROR_SUCCESS
)
1860 for (ptr
= patches
; *ptr
&& r
== ERROR_NO_MORE_ITEMS
; ptr
+= lstrlenW(ptr
))
1862 if (!unsquash_guid(ptr
, patch
))
1864 r
= ERROR_BAD_CONFIGURATION
;
1869 res
= RegGetValueW(prod
, szPatches
, ptr
, RRF_RT_REG_SZ
,
1870 &type
, NULL
, &size
);
1871 if (res
!= ERROR_SUCCESS
)
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
;
1885 if (temp
!= ERROR_SUCCESS
|| !(filter
& state
))
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
;
1900 if (temp
!= ERROR_SUCCESS
|| !(filter
& state
))
1905 temp
= MSIREG_OpenUserDataPatchKey(ptr
, &patchkey
, FALSE
);
1906 RegCloseKey(patchkey
);
1907 if (temp
!= ERROR_SUCCESS
)
1911 else if (context
== MSIINSTALLCONTEXT_MACHINE
)
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
)
1942 lstrcpyW(targetprod
, prodcode
);
1945 *targetctx
= context
;
1949 lstrcpynW(targetsid
, usersid
, *sidsize
);
1950 if (lstrlenW(usersid
) >= *sidsize
)
1951 r
= ERROR_MORE_DATA
;
1956 *sidsize
= lstrlenW(usersid
);
1958 *sidsize
*= sizeof(WCHAR
);
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
];
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
;
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
)
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
)
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
)
2047 if (r
== ERROR_SUCCESS
)
2048 last_index
= dwIndex
;
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
,
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
,
2092 return ERROR_NO_MORE_ITEMS
;