1c2c66affSColin Finck /*
2c2c66affSColin Finck * Implementation of the Microsoft Installer (msi.dll)
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2005 Mike McCormack for CodeWeavers
5c2c66affSColin Finck * Copyright 2005 Aric Stewart for CodeWeavers
6c2c66affSColin Finck *
7c2c66affSColin Finck * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck * License as published by the Free Software Foundation; either
10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck *
12c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15c2c66affSColin Finck * Lesser General Public License for more details.
16c2c66affSColin Finck *
17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck */
21c2c66affSColin Finck
22c42b133eSAmine Khaldi #include <stdarg.h>
23c42b133eSAmine Khaldi
24c42b133eSAmine Khaldi #define COBJMACROS
25c42b133eSAmine Khaldi
26c42b133eSAmine Khaldi #include "windef.h"
27c42b133eSAmine Khaldi #include "winbase.h"
28c42b133eSAmine Khaldi #include "winreg.h"
29c42b133eSAmine Khaldi #include "winnls.h"
30c42b133eSAmine Khaldi #include "shlwapi.h"
31c42b133eSAmine Khaldi #include "wine/debug.h"
32c42b133eSAmine Khaldi #include "msi.h"
33c2c66affSColin Finck #include "msipriv.h"
34c42b133eSAmine Khaldi #include "wincrypt.h"
35c42b133eSAmine Khaldi #include "winver.h"
36c42b133eSAmine Khaldi #include "winuser.h"
37c42b133eSAmine Khaldi #include "sddl.h"
38c2c66affSColin Finck
39c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi);
40c2c66affSColin Finck
unsquash_guid(LPCWSTR in,LPWSTR out)41c2c66affSColin Finck BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
42c2c66affSColin Finck {
43c2c66affSColin Finck DWORD i,n=0;
44c2c66affSColin Finck
45c2c66affSColin Finck if (lstrlenW(in) != 32)
46c2c66affSColin Finck return FALSE;
47c2c66affSColin Finck
48c2c66affSColin Finck out[n++]='{';
49c2c66affSColin Finck for(i=0; i<8; i++)
50c2c66affSColin Finck out[n++] = in[7-i];
51c2c66affSColin Finck out[n++]='-';
52c2c66affSColin Finck for(i=0; i<4; i++)
53c2c66affSColin Finck out[n++] = in[11-i];
54c2c66affSColin Finck out[n++]='-';
55c2c66affSColin Finck for(i=0; i<4; i++)
56c2c66affSColin Finck out[n++] = in[15-i];
57c2c66affSColin Finck out[n++]='-';
58c2c66affSColin Finck for(i=0; i<2; i++)
59c2c66affSColin Finck {
60c2c66affSColin Finck out[n++] = in[17+i*2];
61c2c66affSColin Finck out[n++] = in[16+i*2];
62c2c66affSColin Finck }
63c2c66affSColin Finck out[n++]='-';
64c2c66affSColin Finck for( ; i<8; i++)
65c2c66affSColin Finck {
66c2c66affSColin Finck out[n++] = in[17+i*2];
67c2c66affSColin Finck out[n++] = in[16+i*2];
68c2c66affSColin Finck }
69c2c66affSColin Finck out[n++]='}';
70c2c66affSColin Finck out[n]=0;
71c2c66affSColin Finck return TRUE;
72c2c66affSColin Finck }
73c2c66affSColin Finck
squash_guid(LPCWSTR in,LPWSTR out)74c2c66affSColin Finck BOOL squash_guid(LPCWSTR in, LPWSTR out)
75c2c66affSColin Finck {
76c2c66affSColin Finck DWORD i,n=1;
77c2c66affSColin Finck GUID guid;
78c2c66affSColin Finck
79c2c66affSColin Finck out[0] = 0;
80c2c66affSColin Finck
81c2c66affSColin Finck if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
82c2c66affSColin Finck return FALSE;
83c2c66affSColin Finck
84c2c66affSColin Finck for(i=0; i<8; i++)
85c2c66affSColin Finck out[7-i] = in[n++];
86c2c66affSColin Finck n++;
87c2c66affSColin Finck for(i=0; i<4; i++)
88c2c66affSColin Finck out[11-i] = in[n++];
89c2c66affSColin Finck n++;
90c2c66affSColin Finck for(i=0; i<4; i++)
91c2c66affSColin Finck out[15-i] = in[n++];
92c2c66affSColin Finck n++;
93c2c66affSColin Finck for(i=0; i<2; i++)
94c2c66affSColin Finck {
95c2c66affSColin Finck out[17+i*2] = in[n++];
96c2c66affSColin Finck out[16+i*2] = in[n++];
97c2c66affSColin Finck }
98c2c66affSColin Finck n++;
99c2c66affSColin Finck for( ; i<8; i++)
100c2c66affSColin Finck {
101c2c66affSColin Finck out[17+i*2] = in[n++];
102c2c66affSColin Finck out[16+i*2] = in[n++];
103c2c66affSColin Finck }
104c2c66affSColin Finck out[32]=0;
105c2c66affSColin Finck return TRUE;
106c2c66affSColin Finck }
107c2c66affSColin Finck
108c2c66affSColin Finck
109c2c66affSColin Finck /* tables for encoding and decoding base85 */
110c2c66affSColin Finck static const unsigned char table_dec85[0x80] = {
111c2c66affSColin Finck 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
112c2c66affSColin Finck 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
113c2c66affSColin Finck 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
114c2c66affSColin Finck 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
115c2c66affSColin Finck 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
116c2c66affSColin Finck 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
117c2c66affSColin Finck 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
118c2c66affSColin Finck 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
119c2c66affSColin Finck };
120c2c66affSColin Finck
121c2c66affSColin Finck static const char table_enc85[] =
122c2c66affSColin Finck "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
123c2c66affSColin Finck "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
124c2c66affSColin Finck "yz{}~";
125c2c66affSColin Finck
126c2c66affSColin Finck /*
127c2c66affSColin Finck * Converts a base85 encoded guid into a GUID pointer
128c2c66affSColin Finck * Base85 encoded GUIDs should be 20 characters long.
129c2c66affSColin Finck *
130c2c66affSColin Finck * returns TRUE if successful, FALSE if not
131c2c66affSColin Finck */
decode_base85_guid(LPCWSTR str,GUID * guid)132c2c66affSColin Finck BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
133c2c66affSColin Finck {
134c2c66affSColin Finck DWORD i, val = 0, base = 1, *p;
135c2c66affSColin Finck
136c2c66affSColin Finck if (!str)
137c2c66affSColin Finck return FALSE;
138c2c66affSColin Finck
139c2c66affSColin Finck p = (DWORD*) guid;
140c2c66affSColin Finck for( i=0; i<20; i++ )
141c2c66affSColin Finck {
142c2c66affSColin Finck if( (i%5) == 0 )
143c2c66affSColin Finck {
144c2c66affSColin Finck val = 0;
145c2c66affSColin Finck base = 1;
146c2c66affSColin Finck }
147c2c66affSColin Finck val += table_dec85[str[i]] * base;
148c2c66affSColin Finck if( str[i] >= 0x80 )
149c2c66affSColin Finck return FALSE;
150c2c66affSColin Finck if( table_dec85[str[i]] == 0xff )
151c2c66affSColin Finck return FALSE;
152c2c66affSColin Finck if( (i%5) == 4 )
153c2c66affSColin Finck p[i/5] = val;
154c2c66affSColin Finck base *= 85;
155c2c66affSColin Finck }
156c2c66affSColin Finck return TRUE;
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck /*
160c2c66affSColin Finck * Encodes a base85 guid given a GUID pointer
161c2c66affSColin Finck * Caller should provide a 21 character buffer for the encoded string.
162c2c66affSColin Finck *
163c2c66affSColin Finck * returns TRUE if successful, FALSE if not
164c2c66affSColin Finck */
encode_base85_guid(GUID * guid,LPWSTR str)165c2c66affSColin Finck BOOL encode_base85_guid( GUID *guid, LPWSTR str )
166c2c66affSColin Finck {
167c2c66affSColin Finck unsigned int x, *p, i;
168c2c66affSColin Finck
169c2c66affSColin Finck p = (unsigned int*) guid;
170c2c66affSColin Finck for( i=0; i<4; i++ )
171c2c66affSColin Finck {
172c2c66affSColin Finck x = p[i];
173c2c66affSColin Finck *str++ = table_enc85[x%85];
174c2c66affSColin Finck x = x/85;
175c2c66affSColin Finck *str++ = table_enc85[x%85];
176c2c66affSColin Finck x = x/85;
177c2c66affSColin Finck *str++ = table_enc85[x%85];
178c2c66affSColin Finck x = x/85;
179c2c66affSColin Finck *str++ = table_enc85[x%85];
180c2c66affSColin Finck x = x/85;
181c2c66affSColin Finck *str++ = table_enc85[x%85];
182c2c66affSColin Finck }
183c2c66affSColin Finck *str = 0;
184c2c66affSColin Finck
185c2c66affSColin Finck return TRUE;
186c2c66affSColin Finck }
187c2c66affSColin Finck
msi_version_str_to_dword(LPCWSTR p)188c2c66affSColin Finck DWORD msi_version_str_to_dword(LPCWSTR p)
189c2c66affSColin Finck {
190c2c66affSColin Finck DWORD major, minor = 0, build = 0, version = 0;
191c2c66affSColin Finck
192c2c66affSColin Finck if (!p)
193c2c66affSColin Finck return version;
194c2c66affSColin Finck
195958f1addSwinesync major = wcstol(p, NULL, 10);
196c2c66affSColin Finck
197958f1addSwinesync p = wcschr(p, '.');
198c2c66affSColin Finck if (p)
199c2c66affSColin Finck {
200958f1addSwinesync minor = wcstol(p+1, NULL, 10);
201958f1addSwinesync p = wcschr(p+1, '.');
202c2c66affSColin Finck if (p)
203958f1addSwinesync build = wcstol(p+1, NULL, 10);
204c2c66affSColin Finck }
205c2c66affSColin Finck
206c2c66affSColin Finck return MAKELONG(build, MAKEWORD(minor, major));
207c2c66affSColin Finck }
208c2c66affSColin Finck
msi_reg_set_val_str(HKEY hkey,LPCWSTR name,LPCWSTR value)209c2c66affSColin Finck LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
210c2c66affSColin Finck {
211c2c66affSColin Finck DWORD len;
2120f67ae4bSwinesync if (!value) value = L"";
213c2c66affSColin Finck len = (lstrlenW(value) + 1) * sizeof (WCHAR);
214c2c66affSColin Finck return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
215c2c66affSColin Finck }
216c2c66affSColin Finck
msi_reg_set_val_multi_str(HKEY hkey,LPCWSTR name,LPCWSTR value)217c2c66affSColin Finck LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
218c2c66affSColin Finck {
219c2c66affSColin Finck LPCWSTR p = value;
220c2c66affSColin Finck while (*p) p += lstrlenW(p) + 1;
221c2c66affSColin Finck return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
222c2c66affSColin Finck (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
223c2c66affSColin Finck }
224c2c66affSColin Finck
msi_reg_set_val_dword(HKEY hkey,LPCWSTR name,DWORD val)225c2c66affSColin Finck LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
226c2c66affSColin Finck {
227c2c66affSColin Finck return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
228c2c66affSColin Finck }
229c2c66affSColin Finck
msi_reg_set_subkey_val(HKEY hkey,LPCWSTR path,LPCWSTR name,LPCWSTR val)230c2c66affSColin Finck LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
231c2c66affSColin Finck {
232c2c66affSColin Finck HKEY hsubkey = 0;
233c2c66affSColin Finck LONG r;
234c2c66affSColin Finck
235c2c66affSColin Finck r = RegCreateKeyW( hkey, path, &hsubkey );
236c2c66affSColin Finck if (r != ERROR_SUCCESS)
237c2c66affSColin Finck return r;
238c2c66affSColin Finck r = msi_reg_set_val_str( hsubkey, name, val );
239c2c66affSColin Finck RegCloseKey( hsubkey );
240c2c66affSColin Finck return r;
241c2c66affSColin Finck }
242c2c66affSColin Finck
msi_reg_get_val_str(HKEY hkey,LPCWSTR name)243c2c66affSColin Finck LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
244c2c66affSColin Finck {
245c2c66affSColin Finck DWORD len = 0;
246c2c66affSColin Finck LPWSTR val;
247c2c66affSColin Finck LONG r;
248c2c66affSColin Finck
249c2c66affSColin Finck r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
250c2c66affSColin Finck if (r != ERROR_SUCCESS)
251c2c66affSColin Finck return NULL;
252c2c66affSColin Finck
253c2c66affSColin Finck len += sizeof (WCHAR);
254*f4be6dc3SMikhail val = malloc( len );
255c2c66affSColin Finck if (!val)
256c2c66affSColin Finck return NULL;
257c2c66affSColin Finck val[0] = 0;
258c2c66affSColin Finck RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
259c2c66affSColin Finck return val;
260c2c66affSColin Finck }
261c2c66affSColin Finck
msi_reg_get_val_dword(HKEY hkey,LPCWSTR name,DWORD * val)262c2c66affSColin Finck BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
263c2c66affSColin Finck {
264c2c66affSColin Finck DWORD type, len = sizeof (DWORD);
265c2c66affSColin Finck LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
266c2c66affSColin Finck return r == ERROR_SUCCESS && type == REG_DWORD;
267c2c66affSColin Finck }
268c2c66affSColin Finck
get_user_sid(void)269c2c66affSColin Finck static WCHAR *get_user_sid(void)
270c2c66affSColin Finck {
271c2c66affSColin Finck HANDLE token;
272c2c66affSColin Finck DWORD size = 256;
273c2c66affSColin Finck TOKEN_USER *user;
274c2c66affSColin Finck WCHAR *ret;
275c2c66affSColin Finck
276c2c66affSColin Finck if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &token )) return NULL;
277*f4be6dc3SMikhail if (!(user = malloc( size )))
278c2c66affSColin Finck {
279c2c66affSColin Finck CloseHandle( token );
280c2c66affSColin Finck return NULL;
281c2c66affSColin Finck }
282c2c66affSColin Finck if (!GetTokenInformation( token, TokenUser, user, size, &size ))
283c2c66affSColin Finck {
284*f4be6dc3SMikhail free( user );
285*f4be6dc3SMikhail if (GetLastError() != ERROR_INSUFFICIENT_BUFFER || !(user = malloc( size )))
286c2c66affSColin Finck {
287c2c66affSColin Finck CloseHandle( token );
288c2c66affSColin Finck return NULL;
289c2c66affSColin Finck }
290c2c66affSColin Finck GetTokenInformation( token, TokenUser, user, size, &size );
291c2c66affSColin Finck }
292c2c66affSColin Finck CloseHandle( token );
293c2c66affSColin Finck if (!ConvertSidToStringSidW( user->User.Sid, &ret ))
294c2c66affSColin Finck {
295*f4be6dc3SMikhail free( user );
296c2c66affSColin Finck return NULL;
297c2c66affSColin Finck }
298*f4be6dc3SMikhail free( user );
299c2c66affSColin Finck return ret;
300c2c66affSColin Finck }
301c2c66affSColin Finck
MSIREG_OpenUninstallKey(const WCHAR * product,enum platform platform,HKEY * key,BOOL create)302c2c66affSColin Finck UINT MSIREG_OpenUninstallKey(const WCHAR *product, enum platform platform, HKEY *key, BOOL create)
303c2c66affSColin Finck {
304c3c3655cSwinesync REGSAM access = KEY_ALL_ACCESS;
305c2c66affSColin Finck WCHAR keypath[0x200];
306c2c66affSColin Finck
307c2c66affSColin Finck TRACE("%s\n", debugstr_w(product));
308c2c66affSColin Finck
309c3c3655cSwinesync if (platform == PLATFORM_INTEL)
310c3c3655cSwinesync access |= KEY_WOW64_32KEY;
311c2c66affSColin Finck else
312c3c3655cSwinesync access |= KEY_WOW64_64KEY;
3130f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
314958f1addSwinesync lstrcatW(keypath, product);
315c3c3655cSwinesync if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
316c3c3655cSwinesync return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
317c2c66affSColin Finck }
318c2c66affSColin Finck
MSIREG_DeleteUninstallKey(const WCHAR * product,enum platform platform)319c2c66affSColin Finck UINT MSIREG_DeleteUninstallKey(const WCHAR *product, enum platform platform)
320c2c66affSColin Finck {
321c3c3655cSwinesync REGSAM access = KEY_ALL_ACCESS;
322c3c3655cSwinesync HKEY parent;
323c3c3655cSwinesync LONG r;
324c2c66affSColin Finck
325c2c66affSColin Finck TRACE("%s\n", debugstr_w(product));
326c2c66affSColin Finck
327c3c3655cSwinesync if (platform == PLATFORM_INTEL)
328c3c3655cSwinesync access |= KEY_WOW64_32KEY;
329c2c66affSColin Finck else
330c3c3655cSwinesync access |= KEY_WOW64_64KEY;
3310f67ae4bSwinesync if ((r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\",
3320f67ae4bSwinesync 0, access, &parent))) return r;
333c3c3655cSwinesync r = RegDeleteTreeW(parent, product);
334c3c3655cSwinesync RegCloseKey(parent);
335c3c3655cSwinesync return r;
336c2c66affSColin Finck }
337c2c66affSColin Finck
MSIREG_OpenProductKey(LPCWSTR szProduct,LPCWSTR szUserSid,MSIINSTALLCONTEXT context,HKEY * key,BOOL create)338c2c66affSColin Finck UINT MSIREG_OpenProductKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
339c2c66affSColin Finck {
340c2c66affSColin Finck HKEY root = HKEY_LOCAL_MACHINE;
341c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
342c2c66affSColin Finck WCHAR *usersid = NULL, squashed_pc[SQUASHED_GUID_SIZE], keypath[MAX_PATH];
343c2c66affSColin Finck
344c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
345c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
346c2c66affSColin Finck
347c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
348c2c66affSColin Finck {
3490f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Classes\\Installer\\Products\\");
350958f1addSwinesync lstrcatW( keypath, squashed_pc );
351c2c66affSColin Finck }
352c2c66affSColin Finck else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
353c2c66affSColin Finck {
354c2c66affSColin Finck root = HKEY_CURRENT_USER;
3550f67ae4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Installer\\Products\\" );
356958f1addSwinesync lstrcatW( keypath, squashed_pc );
357c2c66affSColin Finck }
358c2c66affSColin Finck else
359c2c66affSColin Finck {
360c2c66affSColin Finck if (!szUserSid)
361c2c66affSColin Finck {
362c2c66affSColin Finck if (!(usersid = get_user_sid()))
363c2c66affSColin Finck {
364c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
365c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
366c2c66affSColin Finck }
367c2c66affSColin Finck szUserSid = usersid;
368c2c66affSColin Finck }
3690f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath),
3700f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\%s\\Installer\\Products\\%s",
3710f67ae4bSwinesync szUserSid, squashed_pc );
372c2c66affSColin Finck LocalFree(usersid);
373c2c66affSColin Finck }
374c2c66affSColin Finck if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL);
375c2c66affSColin Finck return RegOpenKeyExW(root, keypath, 0, access, key);
376c2c66affSColin Finck }
377c2c66affSColin Finck
MSIREG_DeleteUserProductKey(LPCWSTR szProduct)378c2c66affSColin Finck UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
379c2c66affSColin Finck {
380c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
381c2c66affSColin Finck
382c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
383c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
384c2c66affSColin Finck
3850f67ae4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Installer\\Products\\" );
386958f1addSwinesync lstrcatW( keypath, squashed_pc );
387c2c66affSColin Finck return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
388c2c66affSColin Finck }
389c2c66affSColin Finck
MSIREG_OpenUserPatchesKey(LPCWSTR szPatch,HKEY * key,BOOL create)390c2c66affSColin Finck UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
391c2c66affSColin Finck {
392c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
393c2c66affSColin Finck
394c2c66affSColin Finck if (!squash_guid( szPatch, squashed_pc )) return ERROR_FUNCTION_FAILED;
395c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szPatch), debugstr_w(squashed_pc));
396c2c66affSColin Finck
3970f67ae4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Installer\\Patches\\" );
398958f1addSwinesync lstrcatW( keypath, squashed_pc );
399c2c66affSColin Finck
400c2c66affSColin Finck if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
401c2c66affSColin Finck return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
402c2c66affSColin Finck }
403c2c66affSColin Finck
MSIREG_OpenFeaturesKey(LPCWSTR szProduct,LPCWSTR szUserSid,MSIINSTALLCONTEXT context,HKEY * key,BOOL create)404c2c66affSColin Finck UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context,
405c2c66affSColin Finck HKEY *key, BOOL create)
406c2c66affSColin Finck {
407c2c66affSColin Finck HKEY root = HKEY_LOCAL_MACHINE;
408c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
409c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[MAX_PATH], *usersid = NULL;
410c2c66affSColin Finck
411c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
412c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
413c2c66affSColin Finck
414c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
415c2c66affSColin Finck {
4160f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Classes\\Installer\\Features\\");
417958f1addSwinesync lstrcatW( keypath, squashed_pc );
418c2c66affSColin Finck }
419c2c66affSColin Finck else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
420c2c66affSColin Finck {
421c2c66affSColin Finck root = HKEY_CURRENT_USER;
4220f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Installer\\Features\\");
423958f1addSwinesync lstrcatW( keypath, squashed_pc );
424c2c66affSColin Finck }
425c2c66affSColin Finck else
426c2c66affSColin Finck {
427c2c66affSColin Finck if (!szUserSid)
428c2c66affSColin Finck {
429c2c66affSColin Finck if (!(usersid = get_user_sid()))
430c2c66affSColin Finck {
431c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
432c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
433c2c66affSColin Finck }
434c2c66affSColin Finck szUserSid = usersid;
435c2c66affSColin Finck }
4360f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath),
4370f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\%s\\Installer\\Features\\%s",
4380f67ae4bSwinesync szUserSid, squashed_pc );
439c2c66affSColin Finck LocalFree(usersid);
440c2c66affSColin Finck }
441c2c66affSColin Finck if (create) return RegCreateKeyExW(root, keypath, 0, NULL, 0, access, NULL, key, NULL);
442c2c66affSColin Finck return RegOpenKeyExW(root, keypath, 0, access, key);
443c2c66affSColin Finck }
444c2c66affSColin Finck
MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)445c2c66affSColin Finck UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct)
446c2c66affSColin Finck {
447c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
448c2c66affSColin Finck
449c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
450c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
451c2c66affSColin Finck
4520f67ae4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Installer\\Features\\" );
453958f1addSwinesync lstrcatW( keypath, squashed_pc );
454c2c66affSColin Finck return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
455c2c66affSColin Finck }
456c2c66affSColin Finck
MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct,HKEY * key,BOOL create)457c2c66affSColin Finck static UINT MSIREG_OpenInstallerFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
458c2c66affSColin Finck {
459c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
460c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
461c2c66affSColin Finck
462c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
463c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
464c2c66affSColin Finck
4650f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Features\\");
466958f1addSwinesync lstrcatW( keypath, squashed_pc );
467c2c66affSColin Finck
468c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
469c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
470c2c66affSColin Finck }
471c2c66affSColin Finck
MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct,LPCWSTR szUserSid,MSIINSTALLCONTEXT context,HKEY * key,BOOL create)472c2c66affSColin Finck UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, LPCWSTR szUserSid, MSIINSTALLCONTEXT context,
473c2c66affSColin Finck HKEY *key, BOOL create)
474c2c66affSColin Finck {
4750f67ae4bSwinesync static const WCHAR fmtW[] =
4760f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Products\\%s\\Features";
477c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
478c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200], *usersid = NULL;
479c2c66affSColin Finck
480c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
481c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
482c2c66affSColin Finck
483c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
484c2c66affSColin Finck {
4850f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18", squashed_pc );
486c2c66affSColin Finck }
487c2c66affSColin Finck else
488c2c66affSColin Finck {
489c2c66affSColin Finck if (!szUserSid)
490c2c66affSColin Finck {
491c2c66affSColin Finck if (!(usersid = get_user_sid()))
492c2c66affSColin Finck {
493c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
494c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
495c2c66affSColin Finck }
496c2c66affSColin Finck szUserSid = usersid;
497c2c66affSColin Finck }
4980f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, szUserSid, squashed_pc );
499c2c66affSColin Finck LocalFree(usersid);
500c2c66affSColin Finck }
501c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
502c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
503c2c66affSColin Finck }
504c2c66affSColin Finck
MSIREG_OpenUserComponentsKey(LPCWSTR szComponent,HKEY * key,BOOL create)505c2c66affSColin Finck UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY *key, BOOL create)
506c2c66affSColin Finck {
507c2c66affSColin Finck WCHAR squashed_cc[SQUASHED_GUID_SIZE], keypath[0x200];
508c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
509c2c66affSColin Finck UINT ret;
510c2c66affSColin Finck
511c2c66affSColin Finck if (!squash_guid( szComponent, squashed_cc)) return ERROR_FUNCTION_FAILED;
512c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szComponent), debugstr_w(squashed_cc));
513c2c66affSColin Finck
5140f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Installer\\Components\\");
515958f1addSwinesync lstrcatW( keypath, squashed_cc );
516c2c66affSColin Finck
517c2c66affSColin Finck if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
518c2c66affSColin Finck ret = RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
519c2c66affSColin Finck if (ret != ERROR_FILE_NOT_FOUND) return ret;
520c2c66affSColin Finck
5210f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Classes\\Installer\\Components\\");
522958f1addSwinesync lstrcatW( keypath, squashed_cc );
523c2c66affSColin Finck return RegOpenKeyExW( HKEY_LOCAL_MACHINE, keypath, 0, access, key );
524c2c66affSColin Finck }
525c2c66affSColin Finck
MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent,LPCWSTR szUserSid,HKEY * key,BOOL create)526c2c66affSColin Finck UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid, HKEY *key, BOOL create)
527c2c66affSColin Finck {
5280f67ae4bSwinesync static const WCHAR fmtW[] =
5290f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Components\\%s";
530c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
531c2c66affSColin Finck WCHAR *usersid, squashed_comp[SQUASHED_GUID_SIZE], keypath[0x200];
532c2c66affSColin Finck
533c2c66affSColin Finck if (!squash_guid( szComponent, squashed_comp )) return ERROR_FUNCTION_FAILED;
534c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szComponent), debugstr_w(squashed_comp));
535c2c66affSColin Finck
536c2c66affSColin Finck if (!szUserSid)
537c2c66affSColin Finck {
538c2c66affSColin Finck if (!(usersid = get_user_sid()))
539c2c66affSColin Finck {
540c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
541c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
542c2c66affSColin Finck }
5430f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, usersid, squashed_comp );
544c2c66affSColin Finck LocalFree(usersid);
545c2c66affSColin Finck }
5460f67ae4bSwinesync else swprintf( keypath, ARRAY_SIZE(keypath), fmtW, szUserSid, squashed_comp );
547c2c66affSColin Finck
548c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
549c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
550c2c66affSColin Finck }
551c2c66affSColin Finck
MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent,LPCWSTR szUserSid)552c2c66affSColin Finck UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent, LPCWSTR szUserSid)
553c2c66affSColin Finck {
5540f67ae4bSwinesync static const WCHAR fmtW[] =
5550f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Components";
556c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
557c2c66affSColin Finck WCHAR *usersid, squashed_comp[SQUASHED_GUID_SIZE], keypath[0x200];
558c2c66affSColin Finck HKEY hkey;
559c2c66affSColin Finck LONG r;
560c2c66affSColin Finck
561c2c66affSColin Finck if (!squash_guid( szComponent, squashed_comp )) return ERROR_FUNCTION_FAILED;
562c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szComponent), debugstr_w(squashed_comp));
563c2c66affSColin Finck
564c2c66affSColin Finck if (!szUserSid)
565c2c66affSColin Finck {
566c2c66affSColin Finck if (!(usersid = get_user_sid()))
567c2c66affSColin Finck {
568c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
569c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
570c2c66affSColin Finck }
5710f67ae4bSwinesync swprintf(keypath, ARRAY_SIZE(keypath), fmtW, usersid);
572c2c66affSColin Finck LocalFree(usersid);
573c2c66affSColin Finck }
5740f67ae4bSwinesync else swprintf(keypath, ARRAY_SIZE(keypath), fmtW, szUserSid);
575c2c66affSColin Finck
576c2c66affSColin Finck if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
577c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_comp );
578c2c66affSColin Finck RegCloseKey(hkey);
579c2c66affSColin Finck return r;
580c2c66affSColin Finck }
581c2c66affSColin Finck
MSIREG_OpenUserDataProductKey(LPCWSTR szProduct,MSIINSTALLCONTEXT dwContext,LPCWSTR szUserSid,HKEY * key,BOOL create)582c2c66affSColin Finck UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext, LPCWSTR szUserSid, HKEY *key, BOOL create)
583c2c66affSColin Finck {
5840f67ae4bSwinesync static const WCHAR fmtW[] =
5850f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Products\\%s";
586c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
587c2c66affSColin Finck WCHAR *usersid, squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
588c2c66affSColin Finck
589c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
590c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
591c2c66affSColin Finck
592c2c66affSColin Finck if (dwContext == MSIINSTALLCONTEXT_MACHINE)
5930f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18", squashed_pc );
594c2c66affSColin Finck else if (szUserSid)
5950f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, szUserSid, squashed_pc );
596c2c66affSColin Finck else
597c2c66affSColin Finck {
598c2c66affSColin Finck if (!(usersid = get_user_sid()))
599c2c66affSColin Finck {
600c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
601c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
602c2c66affSColin Finck }
6030f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, usersid, squashed_pc );
604c2c66affSColin Finck LocalFree(usersid);
605c2c66affSColin Finck }
606c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
607c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
608c2c66affSColin Finck }
609c2c66affSColin Finck
MSIREG_OpenUserDataPatchKey(LPCWSTR szPatch,MSIINSTALLCONTEXT dwContext,HKEY * key,BOOL create)610c2c66affSColin Finck UINT MSIREG_OpenUserDataPatchKey(LPCWSTR szPatch, MSIINSTALLCONTEXT dwContext, HKEY *key, BOOL create)
611c2c66affSColin Finck {
6120f67ae4bSwinesync static const WCHAR fmtW[] =
6130f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Patches\\%s";
614c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
615c2c66affSColin Finck WCHAR *usersid, squashed_patch[SQUASHED_GUID_SIZE], keypath[0x200];
616c2c66affSColin Finck
617c2c66affSColin Finck if (!squash_guid( szPatch, squashed_patch )) return ERROR_FUNCTION_FAILED;
618c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szPatch), debugstr_w(squashed_patch));
619c2c66affSColin Finck
620c2c66affSColin Finck if (dwContext == MSIINSTALLCONTEXT_MACHINE)
6210f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18", squashed_patch );
622c2c66affSColin Finck else
623c2c66affSColin Finck {
624c2c66affSColin Finck if (!(usersid = get_user_sid()))
625c2c66affSColin Finck {
626c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
627c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
628c2c66affSColin Finck }
6290f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, usersid, squashed_patch );
630c2c66affSColin Finck LocalFree(usersid);
631c2c66affSColin Finck }
632c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
633c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
634c2c66affSColin Finck }
635c2c66affSColin Finck
MSIREG_DeleteUserDataPatchKey(LPCWSTR patch,MSIINSTALLCONTEXT context)636c2c66affSColin Finck UINT MSIREG_DeleteUserDataPatchKey(LPCWSTR patch, MSIINSTALLCONTEXT context)
637c2c66affSColin Finck {
6380f67ae4bSwinesync static const WCHAR fmtW[] =
6390f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Patches";
640c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
641c2c66affSColin Finck WCHAR *usersid, squashed_patch[SQUASHED_GUID_SIZE], keypath[0x200];
642c2c66affSColin Finck HKEY hkey;
643c2c66affSColin Finck LONG r;
644c2c66affSColin Finck
645c2c66affSColin Finck if (!squash_guid( patch, squashed_patch )) return ERROR_FUNCTION_FAILED;
646c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(patch), debugstr_w(squashed_patch));
647c2c66affSColin Finck
648c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
6490f67ae4bSwinesync swprintf(keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18");
650c2c66affSColin Finck else
651c2c66affSColin Finck {
652c2c66affSColin Finck if (!(usersid = get_user_sid()))
653c2c66affSColin Finck {
654c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
655c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
656c2c66affSColin Finck }
6570f67ae4bSwinesync swprintf(keypath, ARRAY_SIZE(keypath), fmtW, usersid);
658c2c66affSColin Finck LocalFree(usersid);
659c2c66affSColin Finck }
660c2c66affSColin Finck if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
661c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_patch );
662c2c66affSColin Finck RegCloseKey(hkey);
663c2c66affSColin Finck return r;
664c2c66affSColin Finck }
665c2c66affSColin Finck
MSIREG_OpenUserDataProductPatchesKey(LPCWSTR product,MSIINSTALLCONTEXT context,HKEY * key,BOOL create)666c2c66affSColin Finck UINT MSIREG_OpenUserDataProductPatchesKey(LPCWSTR product, MSIINSTALLCONTEXT context, HKEY *key, BOOL create)
667c2c66affSColin Finck {
6680f67ae4bSwinesync static const WCHAR fmtW[] =
6690f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Products\\%s\\Patches";
670c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
671c2c66affSColin Finck WCHAR *usersid, squashed_product[SQUASHED_GUID_SIZE], keypath[0x200];
672c2c66affSColin Finck
673c2c66affSColin Finck if (!squash_guid( product, squashed_product )) return ERROR_FUNCTION_FAILED;
674c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(product), debugstr_w(squashed_product));
675c2c66affSColin Finck
676c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
6770f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18", squashed_product );
678c2c66affSColin Finck else
679c2c66affSColin Finck {
680c2c66affSColin Finck if (!(usersid = get_user_sid()))
681c2c66affSColin Finck {
682c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
683c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
684c2c66affSColin Finck }
6850f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, usersid, squashed_product );
686c2c66affSColin Finck LocalFree(usersid);
687c2c66affSColin Finck }
688c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
689c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
690c2c66affSColin Finck }
691c2c66affSColin Finck
MSIREG_OpenInstallProps(LPCWSTR szProduct,MSIINSTALLCONTEXT dwContext,LPCWSTR szUserSid,HKEY * key,BOOL create)692c2c66affSColin Finck UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, MSIINSTALLCONTEXT dwContext, LPCWSTR szUserSid, HKEY *key, BOOL create)
693c2c66affSColin Finck {
6940f67ae4bSwinesync static const WCHAR fmtW[] =
6950f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Products\\%s\\InstallProperties";
696c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
697c2c66affSColin Finck WCHAR *usersid, squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
698c2c66affSColin Finck
699c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
700c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
701c2c66affSColin Finck
702c2c66affSColin Finck if (dwContext == MSIINSTALLCONTEXT_MACHINE)
7030f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18", squashed_pc );
704c2c66affSColin Finck else if (szUserSid)
7050f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, szUserSid, squashed_pc );
706c2c66affSColin Finck else
707c2c66affSColin Finck {
708c2c66affSColin Finck if (!(usersid = get_user_sid()))
709c2c66affSColin Finck {
710c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
711c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
712c2c66affSColin Finck }
7130f67ae4bSwinesync swprintf( keypath, ARRAY_SIZE(keypath), fmtW, usersid, squashed_pc );
714c2c66affSColin Finck LocalFree(usersid);
715c2c66affSColin Finck }
716c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
717c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
718c2c66affSColin Finck }
719c2c66affSColin Finck
MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct,MSIINSTALLCONTEXT context)720c2c66affSColin Finck UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct, MSIINSTALLCONTEXT context)
721c2c66affSColin Finck {
7220f67ae4bSwinesync static const WCHAR fmtW[] =
7230f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\%s\\Products";
724c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
725c2c66affSColin Finck WCHAR *usersid, squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
726c2c66affSColin Finck HKEY hkey;
727c2c66affSColin Finck LONG r;
728c2c66affSColin Finck
729c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
730c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
731c2c66affSColin Finck
732c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_MACHINE)
7330f67ae4bSwinesync swprintf(keypath, ARRAY_SIZE(keypath), fmtW, L"S-1-5-18");
734c2c66affSColin Finck else
735c2c66affSColin Finck {
736c2c66affSColin Finck if (!(usersid = get_user_sid()))
737c2c66affSColin Finck {
738c2c66affSColin Finck ERR("Failed to retrieve user SID\n");
739c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
740c2c66affSColin Finck }
7410f67ae4bSwinesync swprintf(keypath, ARRAY_SIZE(keypath), fmtW, usersid);
742c2c66affSColin Finck LocalFree(usersid);
743c2c66affSColin Finck }
744c2c66affSColin Finck
745c2c66affSColin Finck if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, &hkey)) return ERROR_SUCCESS;
746c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_pc );
747c2c66affSColin Finck RegCloseKey(hkey);
748c2c66affSColin Finck return r;
749c2c66affSColin Finck }
750c2c66affSColin Finck
MSIREG_DeleteProductKey(LPCWSTR szProduct)751c2c66affSColin Finck UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
752c2c66affSColin Finck {
753c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
754c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE];
755c2c66affSColin Finck HKEY hkey;
756c2c66affSColin Finck LONG r;
757c2c66affSColin Finck
758c2c66affSColin Finck if (!squash_guid( szProduct, squashed_pc )) return ERROR_FUNCTION_FAILED;
759c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProduct), debugstr_w(squashed_pc));
760c2c66affSColin Finck
7610f67ae4bSwinesync if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Products",
7620f67ae4bSwinesync 0, access, &hkey)) return ERROR_SUCCESS;
763c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_pc );
764c2c66affSColin Finck RegCloseKey(hkey);
765c2c66affSColin Finck return r;
766c2c66affSColin Finck }
767c2c66affSColin Finck
MSIREG_OpenPatchesKey(LPCWSTR szPatch,HKEY * key,BOOL create)768c2c66affSColin Finck UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY *key, BOOL create)
769c2c66affSColin Finck {
770c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
771c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE], keypath[0x200];
772c2c66affSColin Finck
773c2c66affSColin Finck if (!squash_guid( szPatch, squashed_pc )) return ERROR_FUNCTION_FAILED;
774c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szPatch), debugstr_w(squashed_pc));
775c2c66affSColin Finck
77674f53b4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Patches\\" );
77774f53b4bSwinesync lstrcatW( keypath, squashed_pc );
778c2c66affSColin Finck
779c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
780c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
781c2c66affSColin Finck }
782c2c66affSColin Finck
MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode,HKEY * key,BOOL create)783c2c66affSColin Finck UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY *key, BOOL create)
784c2c66affSColin Finck {
785c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
786c2c66affSColin Finck WCHAR squashed_uc[SQUASHED_GUID_SIZE], keypath[0x200];
787c2c66affSColin Finck
788c2c66affSColin Finck if (!squash_guid( szUpgradeCode, squashed_uc )) return ERROR_FUNCTION_FAILED;
789c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szUpgradeCode), debugstr_w(squashed_uc));
790c2c66affSColin Finck
7910f67ae4bSwinesync lstrcpyW( keypath, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UpgradeCodes\\" );
792958f1addSwinesync lstrcatW( keypath, squashed_uc );
793c2c66affSColin Finck
794c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
795c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
796c2c66affSColin Finck }
797c2c66affSColin Finck
MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode,HKEY * key,BOOL create)798c2c66affSColin Finck UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
799c2c66affSColin Finck {
800c2c66affSColin Finck WCHAR squashed_uc[SQUASHED_GUID_SIZE], keypath[0x200];
801c2c66affSColin Finck
802c2c66affSColin Finck if (!squash_guid( szUpgradeCode, squashed_uc )) return ERROR_FUNCTION_FAILED;
803c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szUpgradeCode), debugstr_w(squashed_uc));
804c2c66affSColin Finck
8050f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Installer\\UpgradeCodes\\");
806958f1addSwinesync lstrcatW( keypath, squashed_uc );
807c2c66affSColin Finck
808c2c66affSColin Finck if (create) return RegCreateKeyW(HKEY_CURRENT_USER, keypath, key);
809c2c66affSColin Finck return RegOpenKeyW(HKEY_CURRENT_USER, keypath, key);
810c2c66affSColin Finck }
811c2c66affSColin Finck
MSIREG_DeleteUpgradeCodesKey(const WCHAR * code)812c2c66affSColin Finck UINT MSIREG_DeleteUpgradeCodesKey( const WCHAR *code )
813c2c66affSColin Finck {
814c2c66affSColin Finck WCHAR squashed_code[SQUASHED_GUID_SIZE];
815c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
816c2c66affSColin Finck HKEY hkey;
817c2c66affSColin Finck LONG ret;
818c2c66affSColin Finck
819c2c66affSColin Finck if (!squash_guid( code, squashed_code )) return ERROR_FUNCTION_FAILED;
820c2c66affSColin Finck TRACE( "%s squashed %s\n", debugstr_w(code), debugstr_w(squashed_code) );
821c2c66affSColin Finck
8220f67ae4bSwinesync if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UpgradeCodes\\",
8230f67ae4bSwinesync 0, access, &hkey )) return ERROR_SUCCESS;
824c2c66affSColin Finck ret = RegDeleteTreeW( hkey, squashed_code );
825c2c66affSColin Finck RegCloseKey( hkey );
826c2c66affSColin Finck return ret;
827c2c66affSColin Finck }
828c2c66affSColin Finck
MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)829c2c66affSColin Finck UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode)
830c2c66affSColin Finck {
831c2c66affSColin Finck WCHAR squashed_uc[SQUASHED_GUID_SIZE], keypath[0x200];
832c2c66affSColin Finck
833c2c66affSColin Finck if (!squash_guid( szUpgradeCode, squashed_uc )) return ERROR_FUNCTION_FAILED;
834c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szUpgradeCode), debugstr_w(squashed_uc));
835c2c66affSColin Finck
8360f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Microsoft\\Installer\\UpgradeCodes\\");
837958f1addSwinesync lstrcatW( keypath, squashed_uc );
838c2c66affSColin Finck return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
839c2c66affSColin Finck }
840c2c66affSColin Finck
MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)841c2c66affSColin Finck UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode)
842c2c66affSColin Finck {
843c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
844c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE];
845c2c66affSColin Finck HKEY hkey;
846c2c66affSColin Finck LONG r;
847c2c66affSColin Finck
848c2c66affSColin Finck if (!squash_guid( szProductCode, squashed_pc )) return ERROR_FUNCTION_FAILED;
849c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProductCode), debugstr_w(squashed_pc));
850c2c66affSColin Finck
8510f67ae4bSwinesync if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Installer\\Products", 0, access, &hkey))
8520f67ae4bSwinesync return ERROR_SUCCESS;
853c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_pc );
854c2c66affSColin Finck RegCloseKey(hkey);
855c2c66affSColin Finck return r;
856c2c66affSColin Finck }
857c2c66affSColin Finck
MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)858c2c66affSColin Finck UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode)
859c2c66affSColin Finck {
860c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
861c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE];
862c2c66affSColin Finck HKEY hkey;
863c2c66affSColin Finck LONG r;
864c2c66affSColin Finck
865c2c66affSColin Finck if (!squash_guid( szProductCode, squashed_pc )) return ERROR_FUNCTION_FAILED;
866c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szProductCode), debugstr_w(squashed_pc));
867c2c66affSColin Finck
8680f67ae4bSwinesync if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Installer\\Features", 0, access, &hkey))
8690f67ae4bSwinesync return ERROR_SUCCESS;
870c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_pc );
871c2c66affSColin Finck RegCloseKey(hkey);
872c2c66affSColin Finck return r;
873c2c66affSColin Finck }
874c2c66affSColin Finck
MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode,HKEY * key,BOOL create)875c2c66affSColin Finck UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY *key, BOOL create)
876c2c66affSColin Finck {
877c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
878c2c66affSColin Finck WCHAR squashed_uc[SQUASHED_GUID_SIZE], keypath[0x200];
879c2c66affSColin Finck
880c2c66affSColin Finck if (!squash_guid( szUpgradeCode, squashed_uc )) return ERROR_FUNCTION_FAILED;
881c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szUpgradeCode), debugstr_w(squashed_uc));
882c2c66affSColin Finck
8830f67ae4bSwinesync lstrcpyW(keypath, L"Software\\Classes\\Installer\\UpgradeCodes\\");
884958f1addSwinesync lstrcatW( keypath, squashed_uc );
885c2c66affSColin Finck
886c2c66affSColin Finck if (create) return RegCreateKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, key, NULL);
887c2c66affSColin Finck return RegOpenKeyExW(HKEY_LOCAL_MACHINE, keypath, 0, access, key);
888c2c66affSColin Finck }
889c2c66affSColin Finck
MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)890c2c66affSColin Finck UINT MSIREG_DeleteClassesUpgradeCodesKey(LPCWSTR szUpgradeCode)
891c2c66affSColin Finck {
892c2c66affSColin Finck REGSAM access = KEY_WOW64_64KEY | KEY_ALL_ACCESS;
893c2c66affSColin Finck WCHAR squashed_uc[SQUASHED_GUID_SIZE];
894c2c66affSColin Finck HKEY hkey;
895c2c66affSColin Finck LONG r;
896c2c66affSColin Finck
897c2c66affSColin Finck if (!squash_guid( szUpgradeCode, squashed_uc )) return ERROR_FUNCTION_FAILED;
898c2c66affSColin Finck TRACE("%s squashed %s\n", debugstr_w(szUpgradeCode), debugstr_w(squashed_uc));
899c2c66affSColin Finck
9000f67ae4bSwinesync if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Classes\\Installer\\UpgradeCodes", 0, access, &hkey))
9010f67ae4bSwinesync return ERROR_SUCCESS;
902c2c66affSColin Finck r = RegDeleteTreeW( hkey, squashed_uc );
903c2c66affSColin Finck RegCloseKey(hkey);
904c2c66affSColin Finck return r;
905c2c66affSColin Finck }
906c2c66affSColin Finck
907c2c66affSColin Finck /*************************************************************************
908c2c66affSColin Finck * MsiDecomposeDescriptorW [MSI.@]
909c2c66affSColin Finck *
910c2c66affSColin Finck * Decomposes an MSI descriptor into product, feature and component parts.
911c2c66affSColin Finck * An MSI descriptor is a string of the form:
912c2c66affSColin Finck * [base 85 guid] [feature code] '>' [base 85 guid] or
913c2c66affSColin Finck * [base 85 guid] [feature code] '<'
914c2c66affSColin Finck *
915c2c66affSColin Finck * PARAMS
916c2c66affSColin Finck * szDescriptor [I] the descriptor to decompose
917c2c66affSColin Finck * szProduct [O] buffer of MAX_FEATURE_CHARS+1 for the product guid
918c2c66affSColin Finck * szFeature [O] buffer of MAX_FEATURE_CHARS+1 for the feature code
919c2c66affSColin Finck * szComponent [O] buffer of MAX_FEATURE_CHARS+1 for the component guid
920c2c66affSColin Finck * pUsed [O] the length of the descriptor
921c2c66affSColin Finck *
922c2c66affSColin Finck * RETURNS
923c2c66affSColin Finck * ERROR_SUCCESS if everything worked correctly
924c2c66affSColin Finck * ERROR_INVALID_PARAMETER if the descriptor was invalid
925c2c66affSColin Finck *
926c2c66affSColin Finck */
MsiDecomposeDescriptorW(LPCWSTR szDescriptor,LPWSTR szProduct,LPWSTR szFeature,LPWSTR szComponent,LPDWORD pUsed)927c2c66affSColin Finck UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
928c2c66affSColin Finck LPWSTR szFeature, LPWSTR szComponent, LPDWORD pUsed )
929c2c66affSColin Finck {
930c2c66affSColin Finck UINT len;
931c2c66affSColin Finck const WCHAR *p;
932c2c66affSColin Finck GUID product, component;
933c2c66affSColin Finck
934c2c66affSColin Finck TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
935c2c66affSColin Finck szFeature, szComponent, pUsed);
936c2c66affSColin Finck
937c2c66affSColin Finck if (!decode_base85_guid( szDescriptor, &product ))
938c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
939c2c66affSColin Finck
940c2c66affSColin Finck TRACE("product %s\n", debugstr_guid( &product ));
941c2c66affSColin Finck
942958f1addSwinesync if (!(p = wcschr( &szDescriptor[20], '>' )))
943958f1addSwinesync p = wcschr( &szDescriptor[20], '<' );
944c2c66affSColin Finck if (!p)
945c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
946c2c66affSColin Finck
947c2c66affSColin Finck len = (p - &szDescriptor[20]);
948c2c66affSColin Finck if( len > MAX_FEATURE_CHARS )
949c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
950c2c66affSColin Finck
951c2c66affSColin Finck TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
952c2c66affSColin Finck
953c2c66affSColin Finck if (*p == '>')
954c2c66affSColin Finck {
955c2c66affSColin Finck if (!decode_base85_guid( p+1, &component ))
956c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
957c2c66affSColin Finck TRACE( "component %s\n", debugstr_guid(&component) );
958c2c66affSColin Finck }
959c2c66affSColin Finck
960c2c66affSColin Finck if (szProduct)
961c2c66affSColin Finck StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
962c2c66affSColin Finck if (szComponent)
963c2c66affSColin Finck {
964c2c66affSColin Finck if (*p == '>')
965c2c66affSColin Finck StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
966c2c66affSColin Finck else
967c2c66affSColin Finck szComponent[0] = 0;
968c2c66affSColin Finck }
969c2c66affSColin Finck if (szFeature)
970c2c66affSColin Finck {
971c2c66affSColin Finck memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
972c2c66affSColin Finck szFeature[len] = 0;
973c2c66affSColin Finck }
974c2c66affSColin Finck
975c2c66affSColin Finck len = p - szDescriptor + 1;
976c2c66affSColin Finck if (*p == '>') len += 20;
977c2c66affSColin Finck
978c2c66affSColin Finck TRACE("length = %d\n", len);
979c2c66affSColin Finck if (pUsed) *pUsed = len;
980c2c66affSColin Finck
981c2c66affSColin Finck return ERROR_SUCCESS;
982c2c66affSColin Finck }
983c2c66affSColin Finck
MsiDecomposeDescriptorA(LPCSTR szDescriptor,LPSTR szProduct,LPSTR szFeature,LPSTR szComponent,LPDWORD pUsed)984c2c66affSColin Finck UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
985c2c66affSColin Finck LPSTR szFeature, LPSTR szComponent, LPDWORD pUsed )
986c2c66affSColin Finck {
987c2c66affSColin Finck WCHAR product[MAX_FEATURE_CHARS+1];
988c2c66affSColin Finck WCHAR feature[MAX_FEATURE_CHARS+1];
989c2c66affSColin Finck WCHAR component[MAX_FEATURE_CHARS+1];
990c2c66affSColin Finck LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
991c2c66affSColin Finck UINT r;
992c2c66affSColin Finck
993c2c66affSColin Finck TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
994c2c66affSColin Finck szFeature, szComponent, pUsed);
995c2c66affSColin Finck
996c2c66affSColin Finck str = strdupAtoW( szDescriptor );
997c2c66affSColin Finck if( szDescriptor && !str )
998c2c66affSColin Finck return ERROR_OUTOFMEMORY;
999c2c66affSColin Finck
1000c2c66affSColin Finck if (szProduct)
1001c2c66affSColin Finck p = product;
1002c2c66affSColin Finck if (szFeature)
1003c2c66affSColin Finck f = feature;
1004c2c66affSColin Finck if (szComponent)
1005c2c66affSColin Finck c = component;
1006c2c66affSColin Finck
1007c2c66affSColin Finck r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
1008c2c66affSColin Finck
1009c2c66affSColin Finck if (r == ERROR_SUCCESS)
1010c2c66affSColin Finck {
1011c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, p, -1,
1012c2c66affSColin Finck szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
1013c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, f, -1,
1014c2c66affSColin Finck szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
1015c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, c, -1,
1016c2c66affSColin Finck szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
1017c2c66affSColin Finck }
1018c2c66affSColin Finck
1019*f4be6dc3SMikhail free( str );
1020c2c66affSColin Finck
1021c2c66affSColin Finck return r;
1022c2c66affSColin Finck }
1023c2c66affSColin Finck
MsiEnumProductsA(DWORD index,char * lpguid)102402f995b2Swinesync UINT WINAPI MsiEnumProductsA( DWORD index, char *lpguid )
1025c2c66affSColin Finck {
1026c2c66affSColin Finck DWORD r;
1027c2c66affSColin Finck WCHAR szwGuid[GUID_SIZE];
1028c2c66affSColin Finck
102902f995b2Swinesync TRACE( "%lu, %p\n", index, lpguid );
1030c2c66affSColin Finck
1031c2c66affSColin Finck if (NULL == lpguid)
1032c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1033c2c66affSColin Finck r = MsiEnumProductsW(index, szwGuid);
1034c2c66affSColin Finck if( r == ERROR_SUCCESS )
1035c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1036c2c66affSColin Finck
1037c2c66affSColin Finck return r;
1038c2c66affSColin Finck }
1039c2c66affSColin Finck
MsiEnumProductsW(DWORD index,WCHAR * lpguid)104002f995b2Swinesync UINT WINAPI MsiEnumProductsW( DWORD index, WCHAR *lpguid )
1041c2c66affSColin Finck {
104202f995b2Swinesync TRACE("%lu, %p\n", index, lpguid );
1043c2c66affSColin Finck
1044c2c66affSColin Finck if (NULL == lpguid)
1045c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1046c2c66affSColin Finck
10470f67ae4bSwinesync return MsiEnumProductsExW( NULL, L"S-1-1-0", MSIINSTALLCONTEXT_ALL, index, lpguid,
1048c2c66affSColin Finck NULL, NULL, NULL );
1049c2c66affSColin Finck }
1050c2c66affSColin Finck
MsiEnumFeaturesA(const char * szProduct,DWORD index,char * szFeature,char * szParent)105102f995b2Swinesync UINT WINAPI MsiEnumFeaturesA( const char *szProduct, DWORD index, char *szFeature, char *szParent )
1052c2c66affSColin Finck {
1053c2c66affSColin Finck DWORD r;
1054c2c66affSColin Finck WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
105502f995b2Swinesync WCHAR *szwProduct = NULL;
1056c2c66affSColin Finck
105702f995b2Swinesync TRACE( "%s, %lu, %p, %p\n", debugstr_a(szProduct), index, szFeature, szParent );
1058c2c66affSColin Finck
1059c2c66affSColin Finck if( szProduct )
1060c2c66affSColin Finck {
1061c2c66affSColin Finck szwProduct = strdupAtoW( szProduct );
1062c2c66affSColin Finck if( !szwProduct )
1063c2c66affSColin Finck return ERROR_OUTOFMEMORY;
1064c2c66affSColin Finck }
1065c2c66affSColin Finck
1066c2c66affSColin Finck r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
1067c2c66affSColin Finck if( r == ERROR_SUCCESS )
1068c2c66affSColin Finck {
106902f995b2Swinesync WideCharToMultiByte(CP_ACP, 0, szwFeature, -1, szFeature, GUID_SIZE, NULL, NULL);
107002f995b2Swinesync WideCharToMultiByte(CP_ACP, 0, szwParent, -1, szParent, GUID_SIZE, NULL, NULL);
1071c2c66affSColin Finck }
1072c2c66affSColin Finck
1073*f4be6dc3SMikhail free(szwProduct);
1074c2c66affSColin Finck
1075c2c66affSColin Finck return r;
1076c2c66affSColin Finck }
1077c2c66affSColin Finck
MsiEnumFeaturesW(const WCHAR * szProduct,DWORD index,WCHAR * szFeature,WCHAR * szParent)107802f995b2Swinesync UINT WINAPI MsiEnumFeaturesW( const WCHAR *szProduct, DWORD index, WCHAR *szFeature, WCHAR *szParent )
1079c2c66affSColin Finck {
1080c2c66affSColin Finck HKEY hkeyProduct = 0;
1081c2c66affSColin Finck DWORD r, sz;
1082c2c66affSColin Finck
108302f995b2Swinesync TRACE( "%s, %lu, %p, %p\n", debugstr_w(szProduct), index, szFeature, szParent );
1084c2c66affSColin Finck
1085c2c66affSColin Finck if( !szProduct )
1086c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1087c2c66affSColin Finck
1088c2c66affSColin Finck r = MSIREG_OpenInstallerFeaturesKey(szProduct,&hkeyProduct,FALSE);
1089c2c66affSColin Finck if( r != ERROR_SUCCESS )
1090c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1091c2c66affSColin Finck
1092c2c66affSColin Finck sz = GUID_SIZE;
1093c2c66affSColin Finck r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1094c2c66affSColin Finck RegCloseKey(hkeyProduct);
1095c2c66affSColin Finck
1096c2c66affSColin Finck return r;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck
MsiEnumComponentsA(DWORD index,char * lpguid)109902f995b2Swinesync UINT WINAPI MsiEnumComponentsA( DWORD index, char *lpguid )
1100c2c66affSColin Finck {
1101c2c66affSColin Finck DWORD r;
1102c2c66affSColin Finck WCHAR szwGuid[GUID_SIZE];
1103c2c66affSColin Finck
110402f995b2Swinesync TRACE( "%lu, %p\n", index, lpguid );
1105c2c66affSColin Finck
1106c2c66affSColin Finck if (!lpguid) return ERROR_INVALID_PARAMETER;
1107c2c66affSColin Finck
1108c2c66affSColin Finck r = MsiEnumComponentsW(index, szwGuid);
1109c2c66affSColin Finck if( r == ERROR_SUCCESS )
1110c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1111c2c66affSColin Finck
1112c2c66affSColin Finck return r;
1113c2c66affSColin Finck }
1114c2c66affSColin Finck
MsiEnumComponentsW(DWORD index,WCHAR * lpguid)111502f995b2Swinesync UINT WINAPI MsiEnumComponentsW( DWORD index, WCHAR *lpguid )
1116c2c66affSColin Finck {
111702f995b2Swinesync TRACE( "%lu, %p\n", index, lpguid );
1118c2c66affSColin Finck
1119c2c66affSColin Finck if (!lpguid) return ERROR_INVALID_PARAMETER;
1120c2c66affSColin Finck
11210f67ae4bSwinesync return MsiEnumComponentsExW( L"S-1-1-0", MSIINSTALLCONTEXT_ALL, index, lpguid, NULL, NULL, NULL );
1122c2c66affSColin Finck }
1123c2c66affSColin Finck
MsiEnumComponentsExA(const char * user_sid,DWORD ctx,DWORD index,CHAR guid[39],MSIINSTALLCONTEXT * installed_ctx,char * sid,DWORD * sid_len)112402f995b2Swinesync UINT WINAPI MsiEnumComponentsExA( const char *user_sid, DWORD ctx, DWORD index, CHAR guid[39],
112502f995b2Swinesync MSIINSTALLCONTEXT *installed_ctx, char *sid, DWORD *sid_len )
1126c2c66affSColin Finck {
1127c2c66affSColin Finck UINT r;
1128c2c66affSColin Finck WCHAR *user_sidW = NULL, *sidW = NULL, guidW[GUID_SIZE];
1129c2c66affSColin Finck
113002f995b2Swinesync TRACE( "%s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_a(user_sid), ctx, index, guid, installed_ctx,
1131c2c66affSColin Finck sid, sid_len );
1132c2c66affSColin Finck
1133c2c66affSColin Finck if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
1134c2c66affSColin Finck if (user_sid && !(user_sidW = strdupAtoW( user_sid ))) return ERROR_OUTOFMEMORY;
1135*f4be6dc3SMikhail if (sid && !(sidW = malloc( *sid_len * sizeof(WCHAR) )))
1136c2c66affSColin Finck {
1137*f4be6dc3SMikhail free( user_sidW );
1138c2c66affSColin Finck return ERROR_OUTOFMEMORY;
1139c2c66affSColin Finck }
1140c2c66affSColin Finck r = MsiEnumComponentsExW( user_sidW, ctx, index, guidW, installed_ctx, sidW, sid_len );
1141c2c66affSColin Finck if (r == ERROR_SUCCESS)
1142c2c66affSColin Finck {
1143c2c66affSColin Finck if (guid) WideCharToMultiByte( CP_ACP, 0, guidW, GUID_SIZE, guid, GUID_SIZE, NULL, NULL );
1144c2c66affSColin Finck if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
1145c2c66affSColin Finck }
1146*f4be6dc3SMikhail free( user_sidW );
1147*f4be6dc3SMikhail free( sidW );
1148c2c66affSColin Finck return r;
1149c2c66affSColin Finck }
1150c2c66affSColin Finck
fetch_machine_component(DWORD ctx,DWORD index,DWORD * idx,WCHAR guid[39],MSIINSTALLCONTEXT * installed_ctx,LPWSTR sid,LPDWORD sid_len)1151c2c66affSColin Finck static UINT fetch_machine_component( DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
1152c2c66affSColin Finck MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
1153c2c66affSColin Finck {
1154c2c66affSColin Finck UINT r = ERROR_SUCCESS;
1155c2c66affSColin Finck WCHAR component[SQUASHED_GUID_SIZE];
1156c2c66affSColin Finck DWORD i = 0, len_component;
1157c2c66affSColin Finck REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
1158c2c66affSColin Finck HKEY key_components;
1159c2c66affSColin Finck
11600f67ae4bSwinesync if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
11610f67ae4bSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components",
11620f67ae4bSwinesync 0, access, &key_components ))
1163c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1164c2c66affSColin Finck
11659792c08fSwinesync len_component = ARRAY_SIZE( component );
1166c2c66affSColin Finck while (!RegEnumKeyExW( key_components, i, component, &len_component, NULL, NULL, NULL, NULL ))
1167c2c66affSColin Finck {
1168c2c66affSColin Finck if (*idx == index) goto found;
1169c2c66affSColin Finck (*idx)++;
11709792c08fSwinesync len_component = ARRAY_SIZE( component );
1171c2c66affSColin Finck i++;
1172c2c66affSColin Finck }
1173c2c66affSColin Finck RegCloseKey( key_components );
1174c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1175c2c66affSColin Finck
1176c2c66affSColin Finck found:
1177c2c66affSColin Finck if (sid_len)
1178c2c66affSColin Finck {
1179c2c66affSColin Finck if (*sid_len < 1)
1180c2c66affSColin Finck {
1181c2c66affSColin Finck *sid_len = 1;
1182c2c66affSColin Finck r = ERROR_MORE_DATA;
1183c2c66affSColin Finck }
1184c2c66affSColin Finck else if (sid)
1185c2c66affSColin Finck {
1186c2c66affSColin Finck *sid_len = 0;
1187c2c66affSColin Finck sid[0] = 0;
1188c2c66affSColin Finck }
1189c2c66affSColin Finck }
1190c2c66affSColin Finck if (guid) unsquash_guid( component, guid );
1191c2c66affSColin Finck if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
1192c2c66affSColin Finck RegCloseKey( key_components );
1193c2c66affSColin Finck return r;
1194c2c66affSColin Finck }
1195c2c66affSColin Finck
fetch_user_component(const WCHAR * usersid,DWORD ctx,DWORD index,DWORD * idx,WCHAR guid[39],MSIINSTALLCONTEXT * installed_ctx,LPWSTR sid,LPDWORD sid_len)1196c2c66affSColin Finck static UINT fetch_user_component( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx,
1197c2c66affSColin Finck WCHAR guid[39], MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid,
1198c2c66affSColin Finck LPDWORD sid_len )
1199c2c66affSColin Finck {
1200c2c66affSColin Finck UINT r = ERROR_SUCCESS;
1201c2c66affSColin Finck WCHAR path[MAX_PATH], component[SQUASHED_GUID_SIZE], user[128];
1202c2c66affSColin Finck DWORD i = 0, j = 0, len_component, len_user;
1203c2c66affSColin Finck REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
1204c2c66affSColin Finck HKEY key_users, key_components;
1205c2c66affSColin Finck
1206c2c66affSColin Finck if (ctx == MSIINSTALLCONTEXT_USERMANAGED) /* FIXME: where to find these? */
1207c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1208c2c66affSColin Finck
12090f67ae4bSwinesync if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData",
12100f67ae4bSwinesync 0, access, &key_users )) return ERROR_NO_MORE_ITEMS;
1211c2c66affSColin Finck
12129792c08fSwinesync len_user = ARRAY_SIZE( user );
1213c2c66affSColin Finck while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
1214c2c66affSColin Finck {
12150f67ae4bSwinesync if ((wcscmp( usersid, L"S-1-1-0" ) && wcscmp( usersid, user )) ||
12160f67ae4bSwinesync !wcscmp( L"S-1-5-18", user ))
1217c2c66affSColin Finck {
1218c2c66affSColin Finck i++;
12199792c08fSwinesync len_user = ARRAY_SIZE( user );
1220c2c66affSColin Finck continue;
1221c2c66affSColin Finck }
1222958f1addSwinesync lstrcpyW( path, user );
12230f67ae4bSwinesync lstrcatW( path, L"\\Components" );
1224c2c66affSColin Finck if (RegOpenKeyExW( key_users, path, 0, access, &key_components ))
1225c2c66affSColin Finck {
1226c2c66affSColin Finck i++;
12279792c08fSwinesync len_user = ARRAY_SIZE( user );
1228c2c66affSColin Finck continue;
1229c2c66affSColin Finck }
12309792c08fSwinesync len_component = ARRAY_SIZE( component );
1231c2c66affSColin Finck while (!RegEnumKeyExW( key_components, j, component, &len_component, NULL, NULL, NULL, NULL ))
1232c2c66affSColin Finck {
1233c2c66affSColin Finck if (*idx == index) goto found;
1234c2c66affSColin Finck (*idx)++;
12359792c08fSwinesync len_component = ARRAY_SIZE( component );
1236c2c66affSColin Finck j++;
1237c2c66affSColin Finck }
1238c2c66affSColin Finck RegCloseKey( key_components );
12399792c08fSwinesync len_user = ARRAY_SIZE( user );
1240c2c66affSColin Finck i++;
1241c2c66affSColin Finck }
1242c2c66affSColin Finck RegCloseKey( key_users );
1243c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1244c2c66affSColin Finck
1245c2c66affSColin Finck found:
1246c2c66affSColin Finck if (sid_len)
1247c2c66affSColin Finck {
1248c2c66affSColin Finck if (*sid_len < len_user + 1)
1249c2c66affSColin Finck {
1250c2c66affSColin Finck *sid_len = len_user + 1;
1251c2c66affSColin Finck r = ERROR_MORE_DATA;
1252c2c66affSColin Finck }
1253c2c66affSColin Finck else if (sid)
1254c2c66affSColin Finck {
1255c2c66affSColin Finck *sid_len = len_user;
1256958f1addSwinesync lstrcpyW( sid, user );
1257c2c66affSColin Finck }
1258c2c66affSColin Finck }
1259c2c66affSColin Finck if (guid) unsquash_guid( component, guid );
1260c2c66affSColin Finck if (installed_ctx) *installed_ctx = ctx;
1261c2c66affSColin Finck RegCloseKey( key_components );
1262c2c66affSColin Finck RegCloseKey( key_users );
1263c2c66affSColin Finck return r;
1264c2c66affSColin Finck }
1265c2c66affSColin Finck
enum_components(const WCHAR * usersid,DWORD ctx,DWORD index,DWORD * idx,WCHAR guid[39],MSIINSTALLCONTEXT * installed_ctx,LPWSTR sid,LPDWORD sid_len)1266c2c66affSColin Finck static UINT enum_components( const WCHAR *usersid, DWORD ctx, DWORD index, DWORD *idx, WCHAR guid[39],
1267c2c66affSColin Finck MSIINSTALLCONTEXT *installed_ctx, LPWSTR sid, LPDWORD sid_len )
1268c2c66affSColin Finck {
1269c2c66affSColin Finck UINT r = ERROR_NO_MORE_ITEMS;
1270c2c66affSColin Finck WCHAR *user = NULL;
1271c2c66affSColin Finck
1272c2c66affSColin Finck if (!usersid)
1273c2c66affSColin Finck {
1274c2c66affSColin Finck usersid = user = get_user_sid();
1275c2c66affSColin Finck if (!user) return ERROR_FUNCTION_FAILED;
1276c2c66affSColin Finck }
1277c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
1278c2c66affSColin Finck {
1279c2c66affSColin Finck r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERMANAGED, index, idx, guid,
1280c2c66affSColin Finck installed_ctx, sid, sid_len );
1281c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
1282c2c66affSColin Finck }
1283c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
1284c2c66affSColin Finck {
1285c2c66affSColin Finck r = fetch_user_component( usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index, idx, guid,
1286c2c66affSColin Finck installed_ctx, sid, sid_len );
1287c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
1288c2c66affSColin Finck }
1289c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_MACHINE)
1290c2c66affSColin Finck {
1291c2c66affSColin Finck r = fetch_machine_component( MSIINSTALLCONTEXT_MACHINE, index, idx, guid, installed_ctx,
1292c2c66affSColin Finck sid, sid_len );
1293c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
1294c2c66affSColin Finck }
1295c2c66affSColin Finck
1296c2c66affSColin Finck done:
1297c2c66affSColin Finck LocalFree( user );
1298c2c66affSColin Finck return r;
1299c2c66affSColin Finck }
1300c2c66affSColin Finck
MsiEnumComponentsExW(const WCHAR * user_sid,DWORD ctx,DWORD index,WCHAR guid[39],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)130102f995b2Swinesync UINT WINAPI MsiEnumComponentsExW( const WCHAR *user_sid, DWORD ctx, DWORD index, WCHAR guid[39],
130202f995b2Swinesync MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
1303c2c66affSColin Finck {
1304c2c66affSColin Finck UINT r;
1305c2c66affSColin Finck DWORD idx = 0;
1306c2c66affSColin Finck static DWORD last_index;
1307c2c66affSColin Finck
130802f995b2Swinesync TRACE( "%s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_w(user_sid), ctx, index, guid, installed_ctx,
1309c2c66affSColin Finck sid, sid_len );
1310c2c66affSColin Finck
1311c2c66affSColin Finck if ((sid && !sid_len) || !ctx || (user_sid && ctx == MSIINSTALLCONTEXT_MACHINE))
1312c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1313c2c66affSColin Finck
1314c2c66affSColin Finck if (index && index - last_index != 1)
1315c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1316c2c66affSColin Finck
1317c2c66affSColin Finck if (!index) last_index = 0;
1318c2c66affSColin Finck
1319c2c66affSColin Finck r = enum_components( user_sid, ctx, index, &idx, guid, installed_ctx, sid, sid_len );
1320c2c66affSColin Finck if (r == ERROR_SUCCESS)
1321c2c66affSColin Finck last_index = index;
1322c2c66affSColin Finck else
1323c2c66affSColin Finck last_index = 0;
1324c2c66affSColin Finck
1325c2c66affSColin Finck return r;
1326c2c66affSColin Finck }
1327c2c66affSColin Finck
MsiEnumClientsA(const char * szComponent,DWORD index,char * szProduct)132802f995b2Swinesync UINT WINAPI MsiEnumClientsA( const char *szComponent, DWORD index, char *szProduct )
1329c2c66affSColin Finck {
1330c2c66affSColin Finck DWORD r;
1331c2c66affSColin Finck WCHAR szwProduct[GUID_SIZE];
133202f995b2Swinesync WCHAR *szwComponent = NULL;
1333c2c66affSColin Finck
133402f995b2Swinesync TRACE( "%s, %lu, %p\n", debugstr_a(szComponent), index, szProduct );
1335c2c66affSColin Finck
1336c2c66affSColin Finck if ( !szProduct )
1337c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1338c2c66affSColin Finck
1339c2c66affSColin Finck if( szComponent )
1340c2c66affSColin Finck {
1341c2c66affSColin Finck szwComponent = strdupAtoW( szComponent );
1342c2c66affSColin Finck if( !szwComponent )
1343c2c66affSColin Finck return ERROR_OUTOFMEMORY;
1344c2c66affSColin Finck }
1345c2c66affSColin Finck
1346c2c66affSColin Finck r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1347c2c66affSColin Finck if( r == ERROR_SUCCESS )
134802f995b2Swinesync WideCharToMultiByte(CP_ACP, 0, szwProduct, -1, szProduct, GUID_SIZE, NULL, NULL);
1349c2c66affSColin Finck
1350*f4be6dc3SMikhail free(szwComponent);
1351c2c66affSColin Finck
1352c2c66affSColin Finck return r;
1353c2c66affSColin Finck }
1354c2c66affSColin Finck
MsiEnumClientsW(const WCHAR * szComponent,DWORD index,WCHAR * szProduct)135502f995b2Swinesync UINT WINAPI MsiEnumClientsW( const WCHAR *szComponent, DWORD index, WCHAR *szProduct )
1356c2c66affSColin Finck {
1357c2c66affSColin Finck HKEY hkeyComp = 0;
1358c2c66affSColin Finck DWORD r, sz;
1359c2c66affSColin Finck WCHAR szValName[SQUASHED_GUID_SIZE];
1360c2c66affSColin Finck
136102f995b2Swinesync TRACE( "%s, %lu, %p\n", debugstr_w(szComponent), index, szProduct );
1362c2c66affSColin Finck
1363c2c66affSColin Finck if (!szComponent || !*szComponent || !szProduct)
1364c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1365c2c66affSColin Finck
1366c2c66affSColin Finck if (MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkeyComp, FALSE) != ERROR_SUCCESS &&
13670f67ae4bSwinesync MSIREG_OpenUserDataComponentKey(szComponent, L"S-1-5-18", &hkeyComp, FALSE) != ERROR_SUCCESS)
1368c2c66affSColin Finck return ERROR_UNKNOWN_COMPONENT;
1369c2c66affSColin Finck
1370c2c66affSColin Finck /* see if there are any products at all */
1371c2c66affSColin Finck sz = SQUASHED_GUID_SIZE;
1372c2c66affSColin Finck r = RegEnumValueW(hkeyComp, 0, szValName, &sz, NULL, NULL, NULL, NULL);
1373c2c66affSColin Finck if (r != ERROR_SUCCESS)
1374c2c66affSColin Finck {
1375c2c66affSColin Finck RegCloseKey(hkeyComp);
1376c2c66affSColin Finck
1377c2c66affSColin Finck if (index != 0)
1378c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1379c2c66affSColin Finck
1380c2c66affSColin Finck return ERROR_UNKNOWN_COMPONENT;
1381c2c66affSColin Finck }
1382c2c66affSColin Finck
1383c2c66affSColin Finck sz = SQUASHED_GUID_SIZE;
1384c2c66affSColin Finck r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1385c2c66affSColin Finck if( r == ERROR_SUCCESS )
1386c2c66affSColin Finck {
1387c2c66affSColin Finck unsquash_guid(szValName, szProduct);
1388c2c66affSColin Finck TRACE("-> %s\n", debugstr_w(szProduct));
1389c2c66affSColin Finck }
1390c2c66affSColin Finck RegCloseKey(hkeyComp);
1391c2c66affSColin Finck return r;
1392c2c66affSColin Finck }
1393c2c66affSColin Finck
MsiEnumClientsExA(const char * component,const char * usersid,DWORD ctx,DWORD index,char installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,char * sid,DWORD * sid_len)139402f995b2Swinesync UINT WINAPI MsiEnumClientsExA( const char *component, const char *usersid, DWORD ctx, DWORD index,
139502f995b2Swinesync char installed_product[GUID_SIZE], MSIINSTALLCONTEXT *installed_ctx, char *sid,
139602f995b2Swinesync DWORD *sid_len )
1397c2c66affSColin Finck {
139802f995b2Swinesync FIXME( "%s, %s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_a(component), debugstr_a(usersid), ctx, index,
139902f995b2Swinesync installed_product, installed_ctx, sid, sid_len );
1400c2c66affSColin Finck return ERROR_ACCESS_DENIED;
1401c2c66affSColin Finck }
1402c2c66affSColin Finck
MsiEnumClientsExW(const WCHAR * component,const WCHAR * usersid,DWORD ctx,DWORD index,WCHAR installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)140302f995b2Swinesync UINT WINAPI MsiEnumClientsExW( const WCHAR *component, const WCHAR *usersid, DWORD ctx, DWORD index,
140402f995b2Swinesync WCHAR installed_product[GUID_SIZE], MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid,
140502f995b2Swinesync DWORD *sid_len )
1406c2c66affSColin Finck {
140702f995b2Swinesync FIXME( "%s, %s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_w(component), debugstr_w(usersid), ctx, index,
140802f995b2Swinesync installed_product, installed_ctx, sid, sid_len );
1409c2c66affSColin Finck return ERROR_ACCESS_DENIED;
1410c2c66affSColin Finck }
1411c2c66affSColin Finck
MSI_EnumComponentQualifiers(const WCHAR * szComponent,DWORD iIndex,awstring * lpQualBuf,DWORD * pcchQual,awstring * lpAppBuf,DWORD * pcchAppBuf)141202f995b2Swinesync static UINT MSI_EnumComponentQualifiers( const WCHAR *szComponent, DWORD iIndex, awstring *lpQualBuf,
141302f995b2Swinesync DWORD *pcchQual, awstring *lpAppBuf, DWORD *pcchAppBuf )
1414c2c66affSColin Finck {
1415c2c66affSColin Finck DWORD name_sz, val_sz, name_max, val_max, type, ofs;
141602f995b2Swinesync WCHAR *name = NULL, *val = NULL;
1417c2c66affSColin Finck UINT r, r2;
1418c2c66affSColin Finck HKEY key;
1419c2c66affSColin Finck
142002f995b2Swinesync TRACE( "%s, %lu, %p, %p, %p, %p\n", debugstr_w(szComponent), iIndex, lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf );
1421c2c66affSColin Finck
1422c2c66affSColin Finck if (!szComponent)
1423c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1424c2c66affSColin Finck
1425c2c66affSColin Finck r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1426c2c66affSColin Finck if (r != ERROR_SUCCESS)
1427c2c66affSColin Finck return ERROR_UNKNOWN_COMPONENT;
1428c2c66affSColin Finck
1429c2c66affSColin Finck /* figure out how big the name is we want to return */
1430c2c66affSColin Finck name_max = 0x10;
1431c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1432*f4be6dc3SMikhail name = malloc( name_max * sizeof(WCHAR) );
1433c2c66affSColin Finck if (!name)
1434c2c66affSColin Finck goto end;
1435c2c66affSColin Finck
1436c2c66affSColin Finck val_max = 0x10;
1437c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1438*f4be6dc3SMikhail val = malloc( val_max );
1439c2c66affSColin Finck if (!val)
1440c2c66affSColin Finck goto end;
1441c2c66affSColin Finck
1442c2c66affSColin Finck /* loop until we allocate enough memory */
1443c2c66affSColin Finck while (1)
1444c2c66affSColin Finck {
1445c2c66affSColin Finck name_sz = name_max;
1446c2c66affSColin Finck val_sz = val_max;
144702f995b2Swinesync r = RegEnumValueW( key, iIndex, name, &name_sz, NULL, &type, (BYTE *)val, &val_sz );
1448c2c66affSColin Finck if (r == ERROR_SUCCESS)
1449c2c66affSColin Finck break;
1450c2c66affSColin Finck if (r != ERROR_MORE_DATA)
1451c2c66affSColin Finck goto end;
1452c2c66affSColin Finck
1453c2c66affSColin Finck if (type != REG_MULTI_SZ)
1454c2c66affSColin Finck {
145502f995b2Swinesync ERR( "component data has wrong type (%lu)\n", type );
1456c2c66affSColin Finck goto end;
1457c2c66affSColin Finck }
1458c2c66affSColin Finck
1459c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1460c2c66affSColin Finck if (name_sz + 1 >= name_max)
1461c2c66affSColin Finck {
1462c2c66affSColin Finck name_max *= 2;
1463*f4be6dc3SMikhail free( name );
1464*f4be6dc3SMikhail name = malloc( name_max * sizeof (WCHAR) );
1465c2c66affSColin Finck if (!name)
1466c2c66affSColin Finck goto end;
1467c2c66affSColin Finck continue;
1468c2c66affSColin Finck }
1469c2c66affSColin Finck if (val_sz > val_max)
1470c2c66affSColin Finck {
1471c2c66affSColin Finck val_max = val_sz + sizeof (WCHAR);
1472*f4be6dc3SMikhail free( val );
1473*f4be6dc3SMikhail val = malloc( val_max * sizeof (WCHAR) );
1474c2c66affSColin Finck if (!val)
1475c2c66affSColin Finck goto end;
1476c2c66affSColin Finck continue;
1477c2c66affSColin Finck }
147802f995b2Swinesync ERR( "should be enough data, but isn't %lu %lu\n", name_sz, val_sz );
1479c2c66affSColin Finck goto end;
1480c2c66affSColin Finck }
1481c2c66affSColin Finck
1482c2c66affSColin Finck ofs = 0;
1483c2c66affSColin Finck r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1484c2c66affSColin Finck if (r != ERROR_SUCCESS)
1485c2c66affSColin Finck goto end;
1486c2c66affSColin Finck
1487c2c66affSColin Finck TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1488c2c66affSColin Finck
1489c2c66affSColin Finck r = msi_strcpy_to_awstring( name, -1, lpQualBuf, pcchQual );
1490c2c66affSColin Finck r2 = msi_strcpy_to_awstring( val+ofs, -1, lpAppBuf, pcchAppBuf );
1491c2c66affSColin Finck
1492c2c66affSColin Finck if (r2 != ERROR_SUCCESS)
1493c2c66affSColin Finck r = r2;
1494c2c66affSColin Finck
1495c2c66affSColin Finck end:
1496*f4be6dc3SMikhail free(val);
1497*f4be6dc3SMikhail free(name);
1498c2c66affSColin Finck RegCloseKey(key);
1499c2c66affSColin Finck return r;
1500c2c66affSColin Finck }
1501c2c66affSColin Finck
1502c2c66affSColin Finck /*************************************************************************
1503c2c66affSColin Finck * MsiEnumComponentQualifiersA [MSI.@]
1504c2c66affSColin Finck */
MsiEnumComponentQualifiersA(const char * szComponent,DWORD iIndex,char * lpQualifierBuf,DWORD * pcchQualifierBuf,char * lpApplicationDataBuf,DWORD * pcchApplicationDataBuf)150502f995b2Swinesync UINT WINAPI MsiEnumComponentQualifiersA( const char *szComponent, DWORD iIndex, char *lpQualifierBuf,
150602f995b2Swinesync DWORD *pcchQualifierBuf, char *lpApplicationDataBuf,
150702f995b2Swinesync DWORD *pcchApplicationDataBuf )
1508c2c66affSColin Finck {
1509c2c66affSColin Finck awstring qual, appdata;
151002f995b2Swinesync WCHAR *comp;
1511c2c66affSColin Finck UINT r;
1512c2c66affSColin Finck
151302f995b2Swinesync TRACE( "%s, %lu, %p, %p, %p, %p\n", debugstr_a(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf,
151402f995b2Swinesync lpApplicationDataBuf, pcchApplicationDataBuf );
1515c2c66affSColin Finck
1516c2c66affSColin Finck comp = strdupAtoW( szComponent );
1517c2c66affSColin Finck if (szComponent && !comp)
1518c2c66affSColin Finck return ERROR_OUTOFMEMORY;
1519c2c66affSColin Finck
1520c2c66affSColin Finck qual.unicode = FALSE;
1521c2c66affSColin Finck qual.str.a = lpQualifierBuf;
1522c2c66affSColin Finck
1523c2c66affSColin Finck appdata.unicode = FALSE;
1524c2c66affSColin Finck appdata.str.a = lpApplicationDataBuf;
1525c2c66affSColin Finck
1526c2c66affSColin Finck r = MSI_EnumComponentQualifiers( comp, iIndex,
1527c2c66affSColin Finck &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1528*f4be6dc3SMikhail free( comp );
1529c2c66affSColin Finck return r;
1530c2c66affSColin Finck }
1531c2c66affSColin Finck
1532c2c66affSColin Finck /*************************************************************************
1533c2c66affSColin Finck * MsiEnumComponentQualifiersW [MSI.@]
1534c2c66affSColin Finck */
MsiEnumComponentQualifiersW(const WCHAR * szComponent,DWORD iIndex,WCHAR * lpQualifierBuf,DWORD * pcchQualifierBuf,WCHAR * lpApplicationDataBuf,DWORD * pcchApplicationDataBuf)153502f995b2Swinesync UINT WINAPI MsiEnumComponentQualifiersW( const WCHAR *szComponent, DWORD iIndex, WCHAR *lpQualifierBuf,
153602f995b2Swinesync DWORD *pcchQualifierBuf, WCHAR *lpApplicationDataBuf,
153702f995b2Swinesync DWORD *pcchApplicationDataBuf )
1538c2c66affSColin Finck {
1539c2c66affSColin Finck awstring qual, appdata;
1540c2c66affSColin Finck
154102f995b2Swinesync TRACE( "%s, %lu, %p, %p, %p, %p\n", debugstr_w(szComponent), iIndex, lpQualifierBuf, pcchQualifierBuf,
154202f995b2Swinesync lpApplicationDataBuf, pcchApplicationDataBuf );
1543c2c66affSColin Finck
1544c2c66affSColin Finck qual.unicode = TRUE;
1545c2c66affSColin Finck qual.str.w = lpQualifierBuf;
1546c2c66affSColin Finck
1547c2c66affSColin Finck appdata.unicode = TRUE;
1548c2c66affSColin Finck appdata.str.w = lpApplicationDataBuf;
1549c2c66affSColin Finck
155002f995b2Swinesync return MSI_EnumComponentQualifiers( szComponent, iIndex, &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1551c2c66affSColin Finck }
1552c2c66affSColin Finck
1553c2c66affSColin Finck /*************************************************************************
1554c2c66affSColin Finck * MsiEnumRelatedProductsW [MSI.@]
1555c2c66affSColin Finck *
1556c2c66affSColin Finck */
MsiEnumRelatedProductsW(const WCHAR * szUpgradeCode,DWORD dwReserved,DWORD iProductIndex,WCHAR * lpProductBuf)155702f995b2Swinesync UINT WINAPI MsiEnumRelatedProductsW( const WCHAR *szUpgradeCode, DWORD dwReserved, DWORD iProductIndex,
155802f995b2Swinesync WCHAR *lpProductBuf )
1559c2c66affSColin Finck {
1560c2c66affSColin Finck UINT r;
1561c2c66affSColin Finck HKEY hkey;
1562c2c66affSColin Finck WCHAR szKeyName[SQUASHED_GUID_SIZE];
15639792c08fSwinesync DWORD dwSize = ARRAY_SIZE(szKeyName);
1564c2c66affSColin Finck
156502f995b2Swinesync TRACE( "%s, %#lx, %lu, %p\n", debugstr_w(szUpgradeCode), dwReserved, iProductIndex, lpProductBuf );
1566c2c66affSColin Finck
1567c2c66affSColin Finck if (NULL == szUpgradeCode)
1568c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1569c2c66affSColin Finck if (NULL == lpProductBuf)
1570c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1571c2c66affSColin Finck
1572c2c66affSColin Finck r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1573c2c66affSColin Finck if (r != ERROR_SUCCESS)
1574c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1575c2c66affSColin Finck
1576c2c66affSColin Finck r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1577c2c66affSColin Finck if( r == ERROR_SUCCESS )
1578c2c66affSColin Finck unsquash_guid(szKeyName, lpProductBuf);
1579c2c66affSColin Finck RegCloseKey(hkey);
1580c2c66affSColin Finck
1581c2c66affSColin Finck return r;
1582c2c66affSColin Finck }
1583c2c66affSColin Finck
1584c2c66affSColin Finck /*************************************************************************
1585c2c66affSColin Finck * MsiEnumRelatedProductsA [MSI.@]
1586c2c66affSColin Finck *
1587c2c66affSColin Finck */
MsiEnumRelatedProductsA(const char * szUpgradeCode,DWORD dwReserved,DWORD iProductIndex,char * lpProductBuf)158802f995b2Swinesync UINT WINAPI MsiEnumRelatedProductsA( const char *szUpgradeCode, DWORD dwReserved, DWORD iProductIndex,
158902f995b2Swinesync char *lpProductBuf )
1590c2c66affSColin Finck {
159102f995b2Swinesync WCHAR *szwUpgradeCode = NULL;
1592c2c66affSColin Finck WCHAR productW[GUID_SIZE];
1593c2c66affSColin Finck UINT r;
1594c2c66affSColin Finck
159502f995b2Swinesync TRACE( "%s, %#lx, %lu, %p\n", debugstr_a(szUpgradeCode), dwReserved, iProductIndex, lpProductBuf );
1596c2c66affSColin Finck
1597c2c66affSColin Finck if (szUpgradeCode)
1598c2c66affSColin Finck {
1599c2c66affSColin Finck szwUpgradeCode = strdupAtoW( szUpgradeCode );
1600c2c66affSColin Finck if( !szwUpgradeCode )
1601c2c66affSColin Finck return ERROR_OUTOFMEMORY;
1602c2c66affSColin Finck }
1603c2c66affSColin Finck
1604c2c66affSColin Finck r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1605c2c66affSColin Finck iProductIndex, productW );
1606c2c66affSColin Finck if (r == ERROR_SUCCESS)
1607c2c66affSColin Finck {
1608c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1609c2c66affSColin Finck lpProductBuf, GUID_SIZE, NULL, NULL );
1610c2c66affSColin Finck }
1611*f4be6dc3SMikhail free( szwUpgradeCode );
1612c2c66affSColin Finck return r;
1613c2c66affSColin Finck }
1614c2c66affSColin Finck
1615c2c66affSColin Finck /***********************************************************************
1616c2c66affSColin Finck * MsiEnumPatchesExA [MSI.@]
1617c2c66affSColin Finck */
MsiEnumPatchesExA(const char * szProductCode,const char * szUserSid,DWORD dwContext,DWORD dwFilter,DWORD dwIndex,char * szPatchCode,char * szTargetProductCode,MSIINSTALLCONTEXT * pdwTargetProductContext,char * szTargetUserSid,DWORD * pcchTargetUserSid)161802f995b2Swinesync UINT WINAPI MsiEnumPatchesExA( const char *szProductCode, const char *szUserSid, DWORD dwContext, DWORD dwFilter,
161902f995b2Swinesync DWORD dwIndex, char *szPatchCode, char *szTargetProductCode,
162002f995b2Swinesync MSIINSTALLCONTEXT *pdwTargetProductContext, char *szTargetUserSid,
162102f995b2Swinesync DWORD *pcchTargetUserSid )
1622c2c66affSColin Finck {
162302f995b2Swinesync WCHAR *prodcode = NULL, *usersid = NULL, *targsid = NULL;
162402f995b2Swinesync WCHAR patch[GUID_SIZE], targprod[GUID_SIZE];
1625c2c66affSColin Finck DWORD len;
1626c2c66affSColin Finck UINT r;
1627c2c66affSColin Finck
162802f995b2Swinesync TRACE( "%s, %s, %#lx, %lu, %lu, %p, %p, %p, %p, %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
162902f995b2Swinesync dwContext, dwFilter, dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext, szTargetUserSid,
163002f995b2Swinesync pcchTargetUserSid );
1631c2c66affSColin Finck
1632c2c66affSColin Finck if (szTargetUserSid && !pcchTargetUserSid)
1633c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1634c2c66affSColin Finck
1635c2c66affSColin Finck if (szProductCode) prodcode = strdupAtoW(szProductCode);
1636c2c66affSColin Finck if (szUserSid) usersid = strdupAtoW(szUserSid);
1637c2c66affSColin Finck
1638c2c66affSColin Finck r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1639c2c66affSColin Finck patch, targprod, pdwTargetProductContext,
1640c2c66affSColin Finck NULL, &len);
1641c2c66affSColin Finck if (r != ERROR_SUCCESS)
1642c2c66affSColin Finck goto done;
1643c2c66affSColin Finck
1644c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, patch, -1, szPatchCode,
1645c2c66affSColin Finck GUID_SIZE, NULL, NULL);
1646c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, targprod, -1, szTargetProductCode,
1647c2c66affSColin Finck GUID_SIZE, NULL, NULL);
1648c2c66affSColin Finck
1649c2c66affSColin Finck if (!szTargetUserSid)
1650c2c66affSColin Finck {
1651c2c66affSColin Finck if (pcchTargetUserSid)
1652c2c66affSColin Finck *pcchTargetUserSid = len;
1653c2c66affSColin Finck
1654c2c66affSColin Finck goto done;
1655c2c66affSColin Finck }
1656c2c66affSColin Finck
1657*f4be6dc3SMikhail targsid = malloc(++len * sizeof(WCHAR));
1658c2c66affSColin Finck if (!targsid)
1659c2c66affSColin Finck {
1660c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1661c2c66affSColin Finck goto done;
1662c2c66affSColin Finck }
1663c2c66affSColin Finck
1664c2c66affSColin Finck r = MsiEnumPatchesExW(prodcode, usersid, dwContext, dwFilter, dwIndex,
1665c2c66affSColin Finck patch, targprod, pdwTargetProductContext,
1666c2c66affSColin Finck targsid, &len);
1667c2c66affSColin Finck if (r != ERROR_SUCCESS || !szTargetUserSid)
1668c2c66affSColin Finck goto done;
1669c2c66affSColin Finck
1670c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, targsid, -1, szTargetUserSid,
1671c2c66affSColin Finck *pcchTargetUserSid, NULL, NULL);
1672c2c66affSColin Finck
1673c2c66affSColin Finck len = lstrlenW(targsid);
1674c2c66affSColin Finck if (*pcchTargetUserSid < len + 1)
1675c2c66affSColin Finck {
1676c2c66affSColin Finck r = ERROR_MORE_DATA;
1677c2c66affSColin Finck *pcchTargetUserSid = len * sizeof(WCHAR);
1678c2c66affSColin Finck }
1679c2c66affSColin Finck else
1680c2c66affSColin Finck *pcchTargetUserSid = len;
1681c2c66affSColin Finck
1682c2c66affSColin Finck done:
1683*f4be6dc3SMikhail free(prodcode);
1684*f4be6dc3SMikhail free(usersid);
1685*f4be6dc3SMikhail free(targsid);
1686c2c66affSColin Finck
1687c2c66affSColin Finck return r;
1688c2c66affSColin Finck }
1689c2c66affSColin Finck
get_patch_state(const WCHAR * prodcode,const WCHAR * usersid,MSIINSTALLCONTEXT context,WCHAR * patch,MSIPATCHSTATE * state)1690*f4be6dc3SMikhail static UINT get_patch_state(const WCHAR *prodcode, const WCHAR *usersid, MSIINSTALLCONTEXT context,
1691*f4be6dc3SMikhail WCHAR *patch, MSIPATCHSTATE *state)
1692c2c66affSColin Finck {
1693c2c66affSColin Finck DWORD type, val, size;
1694c2c66affSColin Finck HKEY prod, hkey = 0;
1695c2c66affSColin Finck HKEY udpatch = 0;
1696c2c66affSColin Finck LONG res;
1697c2c66affSColin Finck UINT r = ERROR_NO_MORE_ITEMS;
1698c2c66affSColin Finck
1699c2c66affSColin Finck *state = MSIPATCHSTATE_INVALID;
1700c2c66affSColin Finck
1701c2c66affSColin Finck r = MSIREG_OpenUserDataProductKey(prodcode, context,
1702c2c66affSColin Finck usersid, &prod, FALSE);
1703c2c66affSColin Finck if (r != ERROR_SUCCESS)
1704c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1705c2c66affSColin Finck
17060f67ae4bSwinesync res = RegOpenKeyExW(prod, L"Patches", 0, KEY_READ, &hkey);
1707c2c66affSColin Finck if (res != ERROR_SUCCESS)
1708c2c66affSColin Finck goto done;
1709c2c66affSColin Finck
1710c2c66affSColin Finck res = RegOpenKeyExW(hkey, patch, 0, KEY_READ, &udpatch);
1711c2c66affSColin Finck if (res != ERROR_SUCCESS)
1712c2c66affSColin Finck goto done;
1713c2c66affSColin Finck
1714c2c66affSColin Finck size = sizeof(DWORD);
17150f67ae4bSwinesync res = RegGetValueW(udpatch, NULL, L"State", RRF_RT_DWORD, &type, &val, &size);
1716c2c66affSColin Finck if (res != ERROR_SUCCESS ||
1717c2c66affSColin Finck val < MSIPATCHSTATE_APPLIED || val > MSIPATCHSTATE_REGISTERED)
1718c2c66affSColin Finck {
1719c2c66affSColin Finck r = ERROR_BAD_CONFIGURATION;
1720c2c66affSColin Finck goto done;
1721c2c66affSColin Finck }
1722c2c66affSColin Finck
1723c2c66affSColin Finck *state = val;
1724c2c66affSColin Finck r = ERROR_SUCCESS;
1725c2c66affSColin Finck
1726c2c66affSColin Finck done:
1727c2c66affSColin Finck RegCloseKey(udpatch);
1728c2c66affSColin Finck RegCloseKey(hkey);
1729c2c66affSColin Finck RegCloseKey(prod);
1730c2c66affSColin Finck
1731c2c66affSColin Finck return r;
1732c2c66affSColin Finck }
1733c2c66affSColin Finck
check_product_patches(const WCHAR * prodcode,const WCHAR * usersid,MSIINSTALLCONTEXT context,DWORD filter,DWORD index,DWORD * idx,WCHAR * patch,WCHAR * targetprod,MSIINSTALLCONTEXT * targetctx,WCHAR * targetsid,DWORD * sidsize,WCHAR ** transforms)1734*f4be6dc3SMikhail static UINT check_product_patches(const WCHAR *prodcode, const WCHAR *usersid, MSIINSTALLCONTEXT context,
1735*f4be6dc3SMikhail DWORD filter, DWORD index, DWORD *idx, WCHAR *patch, WCHAR *targetprod,
1736*f4be6dc3SMikhail MSIINSTALLCONTEXT *targetctx, WCHAR *targetsid, DWORD *sidsize, WCHAR **transforms)
1737c2c66affSColin Finck {
1738c2c66affSColin Finck MSIPATCHSTATE state = MSIPATCHSTATE_INVALID;
1739c2c66affSColin Finck LPWSTR ptr, patches = NULL;
1740c2c66affSColin Finck HKEY prod, patchkey = 0;
1741c2c66affSColin Finck HKEY localprod = 0, localpatch = 0;
1742c2c66affSColin Finck DWORD type, size;
1743c2c66affSColin Finck LONG res;
1744c2c66affSColin Finck UINT temp, r = ERROR_NO_MORE_ITEMS;
1745c2c66affSColin Finck
1746c2c66affSColin Finck if (MSIREG_OpenProductKey(prodcode, usersid, context,
1747c2c66affSColin Finck &prod, FALSE) != ERROR_SUCCESS)
1748c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
1749c2c66affSColin Finck
1750c2c66affSColin Finck size = 0;
17510f67ae4bSwinesync res = RegGetValueW(prod, L"Patches", L"Patches", RRF_RT_ANY, &type, NULL,
1752c2c66affSColin Finck &size);
1753c2c66affSColin Finck if (res != ERROR_SUCCESS)
1754c2c66affSColin Finck goto done;
1755c2c66affSColin Finck
1756c2c66affSColin Finck if (type != REG_MULTI_SZ)
1757c2c66affSColin Finck {
1758c2c66affSColin Finck r = ERROR_BAD_CONFIGURATION;
1759c2c66affSColin Finck goto done;
1760c2c66affSColin Finck }
1761c2c66affSColin Finck
1762*f4be6dc3SMikhail patches = malloc(size);
1763c2c66affSColin Finck if (!patches)
1764c2c66affSColin Finck {
1765c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1766c2c66affSColin Finck goto done;
1767c2c66affSColin Finck }
1768c2c66affSColin Finck
17690f67ae4bSwinesync res = RegGetValueW(prod, L"Patches", L"Patches", RRF_RT_ANY, &type,
1770c2c66affSColin Finck patches, &size);
1771c2c66affSColin Finck if (res != ERROR_SUCCESS)
1772c2c66affSColin Finck goto done;
1773c2c66affSColin Finck
1774c2c66affSColin Finck for (ptr = patches; *ptr && r == ERROR_NO_MORE_ITEMS; ptr += lstrlenW(ptr) + 1)
1775c2c66affSColin Finck {
1776c2c66affSColin Finck if (!unsquash_guid(ptr, patch))
1777c2c66affSColin Finck {
1778c2c66affSColin Finck r = ERROR_BAD_CONFIGURATION;
1779c2c66affSColin Finck goto done;
1780c2c66affSColin Finck }
1781c2c66affSColin Finck
1782c2c66affSColin Finck size = 0;
17830f67ae4bSwinesync res = RegGetValueW(prod, L"Patches", ptr, RRF_RT_REG_SZ,
1784c2c66affSColin Finck &type, NULL, &size);
1785c2c66affSColin Finck if (res != ERROR_SUCCESS)
1786c2c66affSColin Finck continue;
1787c2c66affSColin Finck
1788c2c66affSColin Finck if (transforms)
1789c2c66affSColin Finck {
1790*f4be6dc3SMikhail *transforms = malloc(size);
1791c2c66affSColin Finck if (!*transforms)
1792c2c66affSColin Finck {
1793c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
1794c2c66affSColin Finck goto done;
1795c2c66affSColin Finck }
1796c2c66affSColin Finck
17970f67ae4bSwinesync res = RegGetValueW(prod, L"Patches", ptr, RRF_RT_REG_SZ,
1798c2c66affSColin Finck &type, *transforms, &size);
1799c2c66affSColin Finck if (res != ERROR_SUCCESS)
1800c2c66affSColin Finck continue;
1801c2c66affSColin Finck }
1802c2c66affSColin Finck
1803c2c66affSColin Finck if (context == MSIINSTALLCONTEXT_USERMANAGED)
1804c2c66affSColin Finck {
1805c2c66affSColin Finck if (!(filter & MSIPATCHSTATE_APPLIED))
1806c2c66affSColin Finck {
1807*f4be6dc3SMikhail temp = get_patch_state(prodcode, usersid, context, ptr, &state);
1808c2c66affSColin Finck if (temp == ERROR_BAD_CONFIGURATION)
1809c2c66affSColin Finck {
1810c2c66affSColin Finck r = ERROR_BAD_CONFIGURATION;
1811c2c66affSColin Finck goto done;
1812c2c66affSColin Finck }
1813c2c66affSColin Finck
1814c2c66affSColin Finck if (temp != ERROR_SUCCESS || !(filter & state))
1815c2c66affSColin Finck continue;
1816c2c66affSColin Finck }
1817c2c66affSColin Finck }
1818c2c66affSColin Finck else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
1819c2c66affSColin Finck {
1820c2c66affSColin Finck if (!(filter & MSIPATCHSTATE_APPLIED))
1821c2c66affSColin Finck {
1822*f4be6dc3SMikhail temp = get_patch_state(prodcode, usersid, context, ptr, &state);
1823c2c66affSColin Finck if (temp == ERROR_BAD_CONFIGURATION)
1824c2c66affSColin Finck {
1825c2c66affSColin Finck r = ERROR_BAD_CONFIGURATION;
1826c2c66affSColin Finck goto done;
1827c2c66affSColin Finck }
1828c2c66affSColin Finck
1829c2c66affSColin Finck if (temp != ERROR_SUCCESS || !(filter & state))
1830c2c66affSColin Finck continue;
1831c2c66affSColin Finck }
1832c2c66affSColin Finck else
1833c2c66affSColin Finck {
1834c2c66affSColin Finck temp = MSIREG_OpenUserDataPatchKey(patch, context,
1835c2c66affSColin Finck &patchkey, FALSE);
1836c2c66affSColin Finck RegCloseKey(patchkey);
1837c2c66affSColin Finck if (temp != ERROR_SUCCESS)
1838c2c66affSColin Finck continue;
1839c2c66affSColin Finck }
1840c2c66affSColin Finck }
1841c2c66affSColin Finck else if (context == MSIINSTALLCONTEXT_MACHINE)
1842c2c66affSColin Finck {
18430f67ae4bSwinesync usersid = L"";
1844c2c66affSColin Finck
1845c2c66affSColin Finck if (MSIREG_OpenUserDataProductKey(prodcode, context, NULL, &localprod, FALSE) == ERROR_SUCCESS &&
18460f67ae4bSwinesync RegOpenKeyExW(localprod, L"Patches", 0, KEY_READ, &localpatch) == ERROR_SUCCESS &&
1847c2c66affSColin Finck RegOpenKeyExW(localpatch, ptr, 0, KEY_READ, &patchkey) == ERROR_SUCCESS)
1848c2c66affSColin Finck {
18490f67ae4bSwinesync res = RegGetValueW(patchkey, NULL, L"State", RRF_RT_REG_DWORD,
1850c2c66affSColin Finck &type, &state, &size);
1851c2c66affSColin Finck
1852c2c66affSColin Finck if (!(filter & state))
1853c2c66affSColin Finck res = ERROR_NO_MORE_ITEMS;
1854c2c66affSColin Finck
1855c2c66affSColin Finck RegCloseKey(patchkey);
1856c2c66affSColin Finck }
1857c2c66affSColin Finck
1858c2c66affSColin Finck RegCloseKey(localpatch);
1859c2c66affSColin Finck RegCloseKey(localprod);
1860c2c66affSColin Finck
1861c2c66affSColin Finck if (res != ERROR_SUCCESS)
1862c2c66affSColin Finck continue;
1863c2c66affSColin Finck }
1864c2c66affSColin Finck
1865c2c66affSColin Finck if (*idx < index)
1866c2c66affSColin Finck {
1867c2c66affSColin Finck (*idx)++;
1868c2c66affSColin Finck continue;
1869c2c66affSColin Finck }
1870c2c66affSColin Finck
1871c2c66affSColin Finck r = ERROR_SUCCESS;
1872c2c66affSColin Finck if (targetprod)
1873c2c66affSColin Finck lstrcpyW(targetprod, prodcode);
1874c2c66affSColin Finck
1875c2c66affSColin Finck if (targetctx)
1876c2c66affSColin Finck *targetctx = context;
1877c2c66affSColin Finck
1878c2c66affSColin Finck if (targetsid)
1879c2c66affSColin Finck {
1880c2c66affSColin Finck lstrcpynW(targetsid, usersid, *sidsize);
1881c2c66affSColin Finck if (lstrlenW(usersid) >= *sidsize)
1882c2c66affSColin Finck r = ERROR_MORE_DATA;
1883c2c66affSColin Finck }
1884c2c66affSColin Finck
1885c2c66affSColin Finck if (sidsize)
1886c2c66affSColin Finck {
1887c2c66affSColin Finck *sidsize = lstrlenW(usersid);
1888c2c66affSColin Finck if (!targetsid)
1889c2c66affSColin Finck *sidsize *= sizeof(WCHAR);
1890c2c66affSColin Finck }
1891c2c66affSColin Finck }
1892c2c66affSColin Finck
1893c2c66affSColin Finck done:
1894c2c66affSColin Finck RegCloseKey(prod);
1895*f4be6dc3SMikhail free(patches);
1896c2c66affSColin Finck
1897c2c66affSColin Finck return r;
1898c2c66affSColin Finck }
1899c2c66affSColin Finck
enum_patches(const WCHAR * szProductCode,const WCHAR * szUserSid,DWORD dwContext,DWORD dwFilter,DWORD dwIndex,DWORD * idx,WCHAR * szPatchCode,WCHAR * szTargetProductCode,MSIINSTALLCONTEXT * pdwTargetProductContext,WCHAR * szTargetUserSid,DWORD * pcchTargetUserSid,WCHAR ** szTransforms)1900*f4be6dc3SMikhail static UINT enum_patches(const WCHAR *szProductCode, const WCHAR *szUserSid, DWORD dwContext, DWORD dwFilter,
1901*f4be6dc3SMikhail DWORD dwIndex, DWORD *idx, WCHAR *szPatchCode, WCHAR *szTargetProductCode,
1902*f4be6dc3SMikhail MSIINSTALLCONTEXT *pdwTargetProductContext, WCHAR *szTargetUserSid, DWORD *pcchTargetUserSid,
1903*f4be6dc3SMikhail WCHAR **szTransforms)
1904c2c66affSColin Finck {
1905c2c66affSColin Finck LPWSTR usersid = NULL;
1906c2c66affSColin Finck UINT r = ERROR_INVALID_PARAMETER;
1907c2c66affSColin Finck
1908c2c66affSColin Finck if (!szUserSid)
1909c2c66affSColin Finck {
1910c2c66affSColin Finck szUserSid = usersid = get_user_sid();
1911c2c66affSColin Finck if (!usersid) return ERROR_FUNCTION_FAILED;
1912c2c66affSColin Finck }
1913c2c66affSColin Finck
1914c2c66affSColin Finck if (dwContext & MSIINSTALLCONTEXT_USERMANAGED)
1915c2c66affSColin Finck {
1916*f4be6dc3SMikhail r = check_product_patches(szProductCode, szUserSid, MSIINSTALLCONTEXT_USERMANAGED, dwFilter, dwIndex, idx,
1917*f4be6dc3SMikhail szPatchCode, szTargetProductCode, pdwTargetProductContext, szTargetUserSid,
1918c2c66affSColin Finck pcchTargetUserSid, szTransforms);
1919c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS)
1920c2c66affSColin Finck goto done;
1921c2c66affSColin Finck }
1922c2c66affSColin Finck
1923c2c66affSColin Finck if (dwContext & MSIINSTALLCONTEXT_USERUNMANAGED)
1924c2c66affSColin Finck {
1925*f4be6dc3SMikhail r = check_product_patches(szProductCode, szUserSid, MSIINSTALLCONTEXT_USERUNMANAGED, dwFilter, dwIndex, idx,
1926*f4be6dc3SMikhail szPatchCode, szTargetProductCode, pdwTargetProductContext, szTargetUserSid,
1927c2c66affSColin Finck pcchTargetUserSid, szTransforms);
1928c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS)
1929c2c66affSColin Finck goto done;
1930c2c66affSColin Finck }
1931c2c66affSColin Finck
1932c2c66affSColin Finck if (dwContext & MSIINSTALLCONTEXT_MACHINE)
1933c2c66affSColin Finck {
1934*f4be6dc3SMikhail r = check_product_patches(szProductCode, szUserSid, MSIINSTALLCONTEXT_MACHINE, dwFilter, dwIndex, idx,
1935*f4be6dc3SMikhail szPatchCode, szTargetProductCode, pdwTargetProductContext, szTargetUserSid,
1936c2c66affSColin Finck pcchTargetUserSid, szTransforms);
1937c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS)
1938c2c66affSColin Finck goto done;
1939c2c66affSColin Finck }
1940c2c66affSColin Finck
1941c2c66affSColin Finck done:
1942c2c66affSColin Finck LocalFree(usersid);
1943c2c66affSColin Finck return r;
1944c2c66affSColin Finck }
1945c2c66affSColin Finck
1946c2c66affSColin Finck /***********************************************************************
1947c2c66affSColin Finck * MsiEnumPatchesExW [MSI.@]
1948c2c66affSColin Finck */
MsiEnumPatchesExW(const WCHAR * szProductCode,const WCHAR * szUserSid,DWORD dwContext,DWORD dwFilter,DWORD dwIndex,WCHAR * szPatchCode,WCHAR * szTargetProductCode,MSIINSTALLCONTEXT * pdwTargetProductContext,WCHAR * szTargetUserSid,DWORD * pcchTargetUserSid)194902f995b2Swinesync UINT WINAPI MsiEnumPatchesExW( const WCHAR *szProductCode, const WCHAR *szUserSid, DWORD dwContext, DWORD dwFilter,
195002f995b2Swinesync DWORD dwIndex, WCHAR *szPatchCode, WCHAR *szTargetProductCode,
195102f995b2Swinesync MSIINSTALLCONTEXT *pdwTargetProductContext, WCHAR *szTargetUserSid,
195202f995b2Swinesync DWORD *pcchTargetUserSid )
1953c2c66affSColin Finck {
1954c2c66affSColin Finck WCHAR squashed_pc[SQUASHED_GUID_SIZE];
1955c2c66affSColin Finck DWORD idx = 0;
1956c2c66affSColin Finck UINT r;
1957c2c66affSColin Finck
1958c2c66affSColin Finck static DWORD last_index;
1959c2c66affSColin Finck
196002f995b2Swinesync TRACE( "%s, %s, %#lx, %lu, %lu, %p, %p, %p, %p, %p)\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
196102f995b2Swinesync dwContext, dwFilter, dwIndex, szPatchCode, szTargetProductCode, pdwTargetProductContext, szTargetUserSid,
196202f995b2Swinesync pcchTargetUserSid );
1963c2c66affSColin Finck
1964c2c66affSColin Finck if (!szProductCode || !squash_guid( szProductCode, squashed_pc ))
1965c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1966c2c66affSColin Finck
19670f67ae4bSwinesync if (szUserSid && !wcscmp( szUserSid, L"S-1-5-18" ))
1968c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1969c2c66affSColin Finck
1970c2c66affSColin Finck if (dwContext & MSIINSTALLCONTEXT_MACHINE && szUserSid)
1971c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1972c2c66affSColin Finck
1973c2c66affSColin Finck if (dwContext <= MSIINSTALLCONTEXT_NONE ||
1974c2c66affSColin Finck dwContext > MSIINSTALLCONTEXT_ALL)
1975c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1976c2c66affSColin Finck
1977c2c66affSColin Finck if (dwFilter <= MSIPATCHSTATE_INVALID || dwFilter > MSIPATCHSTATE_ALL)
1978c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1979c2c66affSColin Finck
1980c2c66affSColin Finck if (dwIndex && dwIndex - last_index != 1)
1981c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
1982c2c66affSColin Finck
1983c2c66affSColin Finck if (dwIndex == 0)
1984c2c66affSColin Finck last_index = 0;
1985c2c66affSColin Finck
1986*f4be6dc3SMikhail r = enum_patches(szProductCode, szUserSid, dwContext, dwFilter, dwIndex, &idx, szPatchCode, szTargetProductCode,
1987*f4be6dc3SMikhail pdwTargetProductContext, szTargetUserSid, pcchTargetUserSid, NULL);
1988c2c66affSColin Finck
1989c2c66affSColin Finck if (r == ERROR_SUCCESS)
1990c2c66affSColin Finck last_index = dwIndex;
1991c2c66affSColin Finck else
1992c2c66affSColin Finck last_index = 0;
1993c2c66affSColin Finck
1994c2c66affSColin Finck return r;
1995c2c66affSColin Finck }
1996c2c66affSColin Finck
1997c2c66affSColin Finck /***********************************************************************
1998c2c66affSColin Finck * MsiEnumPatchesA [MSI.@]
1999c2c66affSColin Finck */
MsiEnumPatchesA(const char * szProduct,DWORD iPatchIndex,char * lpPatchBuf,char * lpTransformsBuf,DWORD * pcchTransformsBuf)200002f995b2Swinesync UINT WINAPI MsiEnumPatchesA( const char *szProduct, DWORD iPatchIndex, char *lpPatchBuf, char *lpTransformsBuf,
200102f995b2Swinesync DWORD *pcchTransformsBuf )
2002c2c66affSColin Finck {
200302f995b2Swinesync WCHAR *product, *transforms, patch[GUID_SIZE];
2004c2c66affSColin Finck DWORD len;
2005c2c66affSColin Finck UINT r;
2006c2c66affSColin Finck
200702f995b2Swinesync TRACE( "%s, %lu, %p, %p, %p\n", debugstr_a(szProduct), iPatchIndex, lpPatchBuf, lpTransformsBuf,
200802f995b2Swinesync pcchTransformsBuf );
2009c2c66affSColin Finck
2010c2c66affSColin Finck if (!szProduct || !lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
2011c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
2012c2c66affSColin Finck
2013c2c66affSColin Finck product = strdupAtoW(szProduct);
2014c2c66affSColin Finck if (!product)
2015c2c66affSColin Finck return ERROR_OUTOFMEMORY;
2016c2c66affSColin Finck
2017c2c66affSColin Finck len = *pcchTransformsBuf;
2018*f4be6dc3SMikhail transforms = malloc(len * sizeof(WCHAR));
2019c2c66affSColin Finck if (!transforms)
2020c2c66affSColin Finck {
2021c2c66affSColin Finck r = ERROR_OUTOFMEMORY;
2022c2c66affSColin Finck goto done;
2023c2c66affSColin Finck }
2024c2c66affSColin Finck
2025c2c66affSColin Finck r = MsiEnumPatchesW(product, iPatchIndex, patch, transforms, &len);
2026c2c66affSColin Finck if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
2027c2c66affSColin Finck goto done;
2028c2c66affSColin Finck
2029c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, patch, -1, lpPatchBuf,
2030c2c66affSColin Finck GUID_SIZE, NULL, NULL);
2031c2c66affSColin Finck
2032c2c66affSColin Finck if (!WideCharToMultiByte(CP_ACP, 0, transforms, -1, lpTransformsBuf,
2033c2c66affSColin Finck *pcchTransformsBuf, NULL, NULL))
2034c2c66affSColin Finck r = ERROR_MORE_DATA;
2035c2c66affSColin Finck
2036c2c66affSColin Finck if (r == ERROR_MORE_DATA)
2037c2c66affSColin Finck {
2038c2c66affSColin Finck lpTransformsBuf[*pcchTransformsBuf - 1] = '\0';
2039c2c66affSColin Finck *pcchTransformsBuf = len * 2;
2040c2c66affSColin Finck }
2041c2c66affSColin Finck else
2042c2c66affSColin Finck *pcchTransformsBuf = strlen( lpTransformsBuf );
2043c2c66affSColin Finck
2044c2c66affSColin Finck done:
2045*f4be6dc3SMikhail free(transforms);
2046*f4be6dc3SMikhail free(product);
2047c2c66affSColin Finck
2048c2c66affSColin Finck return r;
2049c2c66affSColin Finck }
2050c2c66affSColin Finck
2051c2c66affSColin Finck /***********************************************************************
2052c2c66affSColin Finck * MsiEnumPatchesW [MSI.@]
2053c2c66affSColin Finck */
MsiEnumPatchesW(const WCHAR * szProduct,DWORD iPatchIndex,WCHAR * lpPatchBuf,WCHAR * lpTransformsBuf,DWORD * pcchTransformsBuf)205402f995b2Swinesync UINT WINAPI MsiEnumPatchesW( const WCHAR *szProduct, DWORD iPatchIndex, WCHAR *lpPatchBuf, WCHAR *lpTransformsBuf,
205502f995b2Swinesync DWORD *pcchTransformsBuf )
2056c2c66affSColin Finck {
2057c2c66affSColin Finck WCHAR *transforms = NULL, squashed_pc[SQUASHED_GUID_SIZE];
2058c2c66affSColin Finck HKEY prod;
2059c2c66affSColin Finck DWORD idx = 0;
2060c2c66affSColin Finck UINT r;
2061c2c66affSColin Finck
206202f995b2Swinesync TRACE( "%s, %lu, %p, %p, %p)\n", debugstr_w(szProduct), iPatchIndex, lpPatchBuf, lpTransformsBuf,
206302f995b2Swinesync pcchTransformsBuf );
2064c2c66affSColin Finck
2065c2c66affSColin Finck if (!szProduct || !squash_guid( szProduct, squashed_pc ))
2066c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
2067c2c66affSColin Finck
2068c2c66affSColin Finck if (!lpPatchBuf || !lpTransformsBuf || !pcchTransformsBuf)
2069c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
2070c2c66affSColin Finck
2071c2c66affSColin Finck if (MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERMANAGED,
2072c2c66affSColin Finck &prod, FALSE) != ERROR_SUCCESS &&
2073c2c66affSColin Finck MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2074c2c66affSColin Finck &prod, FALSE) != ERROR_SUCCESS &&
2075c2c66affSColin Finck MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE,
2076c2c66affSColin Finck &prod, FALSE) != ERROR_SUCCESS)
2077c2c66affSColin Finck return ERROR_UNKNOWN_PRODUCT;
2078c2c66affSColin Finck
2079c2c66affSColin Finck RegCloseKey(prod);
2080c2c66affSColin Finck
2081*f4be6dc3SMikhail r = enum_patches(szProduct, NULL, MSIINSTALLCONTEXT_ALL, MSIPATCHSTATE_ALL, iPatchIndex, &idx, lpPatchBuf, NULL,
2082*f4be6dc3SMikhail NULL, NULL, NULL, &transforms);
2083c2c66affSColin Finck if (r != ERROR_SUCCESS)
2084c2c66affSColin Finck goto done;
2085c2c66affSColin Finck
2086c2c66affSColin Finck lstrcpynW(lpTransformsBuf, transforms, *pcchTransformsBuf);
2087c2c66affSColin Finck if (*pcchTransformsBuf <= lstrlenW(transforms))
2088c2c66affSColin Finck {
2089c2c66affSColin Finck r = ERROR_MORE_DATA;
2090c2c66affSColin Finck *pcchTransformsBuf = lstrlenW(transforms);
2091c2c66affSColin Finck }
2092c2c66affSColin Finck else
2093c2c66affSColin Finck *pcchTransformsBuf = lstrlenW(transforms);
2094c2c66affSColin Finck
2095c2c66affSColin Finck done:
2096*f4be6dc3SMikhail free(transforms);
2097c2c66affSColin Finck return r;
2098c2c66affSColin Finck }
2099c2c66affSColin Finck
MsiEnumProductsExA(const char * product,const char * usersid,DWORD ctx,DWORD index,char installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,char * sid,DWORD * sid_len)210002f995b2Swinesync UINT WINAPI MsiEnumProductsExA( const char *product, const char *usersid, DWORD ctx, DWORD index,
210102f995b2Swinesync char installed_product[GUID_SIZE], MSIINSTALLCONTEXT *installed_ctx, char *sid,
210202f995b2Swinesync DWORD *sid_len )
2103c2c66affSColin Finck {
2104c2c66affSColin Finck UINT r;
2105c2c66affSColin Finck WCHAR installed_productW[GUID_SIZE], *productW = NULL, *usersidW = NULL, *sidW = NULL;
2106c2c66affSColin Finck
210702f995b2Swinesync TRACE( "%s, %s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_a(product), debugstr_a(usersid), ctx, index,
210802f995b2Swinesync installed_product, installed_ctx, sid, sid_len );
2109c2c66affSColin Finck
2110c2c66affSColin Finck if (sid && !sid_len) return ERROR_INVALID_PARAMETER;
2111c2c66affSColin Finck if (product && !(productW = strdupAtoW( product ))) return ERROR_OUTOFMEMORY;
2112c2c66affSColin Finck if (usersid && !(usersidW = strdupAtoW( usersid )))
2113c2c66affSColin Finck {
2114*f4be6dc3SMikhail free( productW );
2115c2c66affSColin Finck return ERROR_OUTOFMEMORY;
2116c2c66affSColin Finck }
2117*f4be6dc3SMikhail if (sid && !(sidW = malloc( *sid_len * sizeof(WCHAR) )))
2118c2c66affSColin Finck {
2119*f4be6dc3SMikhail free( usersidW );
2120*f4be6dc3SMikhail free( productW );
2121c2c66affSColin Finck return ERROR_OUTOFMEMORY;
2122c2c66affSColin Finck }
2123c2c66affSColin Finck r = MsiEnumProductsExW( productW, usersidW, ctx, index, installed_productW,
2124c2c66affSColin Finck installed_ctx, sidW, sid_len );
2125c2c66affSColin Finck if (r == ERROR_SUCCESS)
2126c2c66affSColin Finck {
2127c2c66affSColin Finck if (installed_product) WideCharToMultiByte( CP_ACP, 0, installed_productW, GUID_SIZE,
2128c2c66affSColin Finck installed_product, GUID_SIZE, NULL, NULL );
2129c2c66affSColin Finck if (sid) WideCharToMultiByte( CP_ACP, 0, sidW, *sid_len + 1, sid, *sid_len + 1, NULL, NULL );
2130c2c66affSColin Finck }
2131*f4be6dc3SMikhail free( productW );
2132*f4be6dc3SMikhail free( usersidW );
2133*f4be6dc3SMikhail free( sidW );
2134c2c66affSColin Finck return r;
2135c2c66affSColin Finck }
2136c2c66affSColin Finck
fetch_machine_product(const WCHAR * match,DWORD index,DWORD * idx,WCHAR installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)2137c2c66affSColin Finck static UINT fetch_machine_product( const WCHAR *match, DWORD index, DWORD *idx,
2138c2c66affSColin Finck WCHAR installed_product[GUID_SIZE],
2139c2c66affSColin Finck MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
2140c2c66affSColin Finck {
2141c2c66affSColin Finck UINT r;
2142c2c66affSColin Finck WCHAR product[SQUASHED_GUID_SIZE];
2143c2c66affSColin Finck DWORD i = 0, len;
2144c2c66affSColin Finck REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
2145c2c66affSColin Finck HKEY key;
2146c2c66affSColin Finck
21470f67ae4bSwinesync if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Classes\\Installer\\Products", 0, access, &key ))
2148c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
2149c2c66affSColin Finck
21509792c08fSwinesync len = ARRAY_SIZE( product );
2151c2c66affSColin Finck while (!RegEnumKeyExW( key, i, product, &len, NULL, NULL, NULL, NULL ))
2152c2c66affSColin Finck {
2153958f1addSwinesync if (match && wcscmp( match, product ))
2154c2c66affSColin Finck {
2155c2c66affSColin Finck i++;
21569792c08fSwinesync len = ARRAY_SIZE( product );
2157c2c66affSColin Finck continue;
2158c2c66affSColin Finck }
2159c2c66affSColin Finck if (*idx == index) goto found;
2160c2c66affSColin Finck (*idx)++;
21619792c08fSwinesync len = ARRAY_SIZE( product );
2162c2c66affSColin Finck i++;
2163c2c66affSColin Finck }
2164c2c66affSColin Finck RegCloseKey( key );
2165c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
2166c2c66affSColin Finck
2167c2c66affSColin Finck found:
2168c2c66affSColin Finck if (sid_len && *sid_len < 1)
2169c2c66affSColin Finck {
2170c2c66affSColin Finck *sid_len = 1;
2171c2c66affSColin Finck r = ERROR_MORE_DATA;
2172c2c66affSColin Finck }
2173c2c66affSColin Finck else
2174c2c66affSColin Finck {
2175c2c66affSColin Finck if (installed_product) unsquash_guid( product, installed_product );
2176c2c66affSColin Finck if (installed_ctx) *installed_ctx = MSIINSTALLCONTEXT_MACHINE;
2177c2c66affSColin Finck if (sid)
2178c2c66affSColin Finck {
2179c2c66affSColin Finck sid[0] = 0;
2180c2c66affSColin Finck *sid_len = 0;
2181c2c66affSColin Finck }
2182c2c66affSColin Finck r = ERROR_SUCCESS;
2183c2c66affSColin Finck }
2184c2c66affSColin Finck RegCloseKey( key );
2185c2c66affSColin Finck return r;
2186c2c66affSColin Finck }
2187c2c66affSColin Finck
fetch_user_product(const WCHAR * match,const WCHAR * usersid,DWORD ctx,DWORD index,DWORD * idx,WCHAR installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)2188c2c66affSColin Finck static UINT fetch_user_product( const WCHAR *match, const WCHAR *usersid, DWORD ctx, DWORD index,
2189c2c66affSColin Finck DWORD *idx, WCHAR installed_product[GUID_SIZE],
2190c2c66affSColin Finck MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
2191c2c66affSColin Finck {
2192c2c66affSColin Finck UINT r;
2193c2c66affSColin Finck const WCHAR *subkey;
2194c2c66affSColin Finck WCHAR path[MAX_PATH], product[SQUASHED_GUID_SIZE], user[128];
2195c2c66affSColin Finck DWORD i = 0, j = 0, len_product, len_user;
2196c2c66affSColin Finck REGSAM access = KEY_ENUMERATE_SUB_KEYS | KEY_WOW64_64KEY;
2197c2c66affSColin Finck HKEY key_users, key_products;
2198c2c66affSColin Finck
2199c2c66affSColin Finck if (ctx == MSIINSTALLCONTEXT_USERMANAGED)
2200c2c66affSColin Finck {
22010f67ae4bSwinesync subkey = L"\\Installer\\Products";
22020f67ae4bSwinesync if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed",
22030f67ae4bSwinesync 0, access, &key_users )) return ERROR_NO_MORE_ITEMS;
2204c2c66affSColin Finck }
2205c2c66affSColin Finck else if (ctx == MSIINSTALLCONTEXT_USERUNMANAGED)
2206c2c66affSColin Finck {
22070f67ae4bSwinesync subkey = L"\\Software\\Microsoft\\Installer\\Products";
2208c2c66affSColin Finck if (RegOpenKeyExW( HKEY_USERS, NULL, 0, access, &key_users ))
2209c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
2210c2c66affSColin Finck }
2211c2c66affSColin Finck else return ERROR_INVALID_PARAMETER;
2212c2c66affSColin Finck
22139792c08fSwinesync len_user = ARRAY_SIZE( user );
2214c2c66affSColin Finck while (!RegEnumKeyExW( key_users, i, user, &len_user, NULL, NULL, NULL, NULL ))
2215c2c66affSColin Finck {
22160f67ae4bSwinesync if (wcscmp( usersid, user ) && wcscmp( usersid, L"S-1-1-0" ))
2217c2c66affSColin Finck {
2218c2c66affSColin Finck i++;
22199792c08fSwinesync len_user = ARRAY_SIZE( user );
2220c2c66affSColin Finck continue;
2221c2c66affSColin Finck }
2222958f1addSwinesync lstrcpyW( path, user );
2223958f1addSwinesync lstrcatW( path, subkey );
2224c2c66affSColin Finck if (RegOpenKeyExW( key_users, path, 0, access, &key_products ))
2225c2c66affSColin Finck {
2226c2c66affSColin Finck i++;
22279792c08fSwinesync len_user = ARRAY_SIZE( user );
2228c2c66affSColin Finck continue;
2229c2c66affSColin Finck }
22309792c08fSwinesync len_product = ARRAY_SIZE( product );
2231c2c66affSColin Finck while (!RegEnumKeyExW( key_products, j, product, &len_product, NULL, NULL, NULL, NULL ))
2232c2c66affSColin Finck {
2233958f1addSwinesync if (match && wcscmp( match, product ))
2234c2c66affSColin Finck {
2235c2c66affSColin Finck j++;
22369792c08fSwinesync len_product = ARRAY_SIZE( product );
2237c2c66affSColin Finck continue;
2238c2c66affSColin Finck }
2239c2c66affSColin Finck if (*idx == index) goto found;
2240c2c66affSColin Finck (*idx)++;
22419792c08fSwinesync len_product = ARRAY_SIZE( product );
2242c2c66affSColin Finck j++;
2243c2c66affSColin Finck }
2244c2c66affSColin Finck RegCloseKey( key_products );
22459792c08fSwinesync len_user = ARRAY_SIZE( user );
2246c2c66affSColin Finck i++;
2247c2c66affSColin Finck }
2248c2c66affSColin Finck RegCloseKey( key_users );
2249c2c66affSColin Finck return ERROR_NO_MORE_ITEMS;
2250c2c66affSColin Finck
2251c2c66affSColin Finck found:
2252c2c66affSColin Finck if (sid_len && *sid_len <= len_user)
2253c2c66affSColin Finck {
2254c2c66affSColin Finck *sid_len = len_user;
2255c2c66affSColin Finck r = ERROR_MORE_DATA;
2256c2c66affSColin Finck }
2257c2c66affSColin Finck else
2258c2c66affSColin Finck {
2259c2c66affSColin Finck if (installed_product) unsquash_guid( product, installed_product );
2260c2c66affSColin Finck if (installed_ctx) *installed_ctx = ctx;
2261c2c66affSColin Finck if (sid)
2262c2c66affSColin Finck {
2263958f1addSwinesync lstrcpyW( sid, user );
2264c2c66affSColin Finck *sid_len = len_user;
2265c2c66affSColin Finck }
2266c2c66affSColin Finck r = ERROR_SUCCESS;
2267c2c66affSColin Finck }
2268c2c66affSColin Finck RegCloseKey( key_products );
2269c2c66affSColin Finck RegCloseKey( key_users );
2270c2c66affSColin Finck return r;
2271c2c66affSColin Finck }
2272c2c66affSColin Finck
enum_products(const WCHAR * product,const WCHAR * usersid,DWORD ctx,DWORD index,DWORD * idx,WCHAR installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)2273c2c66affSColin Finck static UINT enum_products( const WCHAR *product, const WCHAR *usersid, DWORD ctx, DWORD index,
2274c2c66affSColin Finck DWORD *idx, WCHAR installed_product[GUID_SIZE],
2275c2c66affSColin Finck MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid, DWORD *sid_len )
2276c2c66affSColin Finck {
2277c2c66affSColin Finck UINT r = ERROR_NO_MORE_ITEMS;
2278c2c66affSColin Finck WCHAR *user = NULL;
2279c2c66affSColin Finck
2280c2c66affSColin Finck if (!usersid)
2281c2c66affSColin Finck {
2282c2c66affSColin Finck usersid = user = get_user_sid();
2283c2c66affSColin Finck if (!user) return ERROR_FUNCTION_FAILED;
2284c2c66affSColin Finck }
2285c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_MACHINE)
2286c2c66affSColin Finck {
2287c2c66affSColin Finck r = fetch_machine_product( product, index, idx, installed_product, installed_ctx,
2288c2c66affSColin Finck sid, sid_len );
2289c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
2290c2c66affSColin Finck }
2291c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_USERUNMANAGED)
2292c2c66affSColin Finck {
2293c2c66affSColin Finck r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERUNMANAGED, index,
2294c2c66affSColin Finck idx, installed_product, installed_ctx, sid, sid_len );
2295c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
2296c2c66affSColin Finck }
2297c2c66affSColin Finck if (ctx & MSIINSTALLCONTEXT_USERMANAGED)
2298c2c66affSColin Finck {
2299c2c66affSColin Finck r = fetch_user_product( product, usersid, MSIINSTALLCONTEXT_USERMANAGED, index,
2300c2c66affSColin Finck idx, installed_product, installed_ctx, sid, sid_len );
2301c2c66affSColin Finck if (r != ERROR_NO_MORE_ITEMS) goto done;
2302c2c66affSColin Finck }
2303c2c66affSColin Finck
2304c2c66affSColin Finck done:
2305c2c66affSColin Finck LocalFree( user );
2306c2c66affSColin Finck return r;
2307c2c66affSColin Finck }
2308c2c66affSColin Finck
MsiEnumProductsExW(const WCHAR * product,const WCHAR * usersid,DWORD ctx,DWORD index,WCHAR installed_product[GUID_SIZE],MSIINSTALLCONTEXT * installed_ctx,WCHAR * sid,DWORD * sid_len)230902f995b2Swinesync UINT WINAPI MsiEnumProductsExW( const WCHAR *product, const WCHAR *usersid, DWORD ctx, DWORD index,
231002f995b2Swinesync WCHAR installed_product[GUID_SIZE], MSIINSTALLCONTEXT *installed_ctx, WCHAR *sid,
231102f995b2Swinesync DWORD *sid_len )
2312c2c66affSColin Finck {
2313c2c66affSColin Finck UINT r;
2314c2c66affSColin Finck DWORD idx = 0;
2315c2c66affSColin Finck static DWORD last_index;
2316c2c66affSColin Finck
231702f995b2Swinesync TRACE( "%s, %s, %#lx, %lu, %p, %p, %p, %p\n", debugstr_w(product), debugstr_w(usersid), ctx, index,
231802f995b2Swinesync installed_product, installed_ctx, sid, sid_len );
2319c2c66affSColin Finck
2320c2c66affSColin Finck if ((sid && !sid_len) || !ctx || (usersid && ctx == MSIINSTALLCONTEXT_MACHINE))
2321c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
2322c2c66affSColin Finck
2323c2c66affSColin Finck if (index && index - last_index != 1)
2324c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
2325c2c66affSColin Finck
2326c2c66affSColin Finck if (!index) last_index = 0;
2327c2c66affSColin Finck
2328c2c66affSColin Finck r = enum_products( product, usersid, ctx, index, &idx, installed_product, installed_ctx,
2329c2c66affSColin Finck sid, sid_len );
2330c2c66affSColin Finck if (r == ERROR_SUCCESS)
2331c2c66affSColin Finck last_index = index;
2332c2c66affSColin Finck else
2333c2c66affSColin Finck last_index = 0;
2334c2c66affSColin Finck
2335c2c66affSColin Finck return r;
2336c2c66affSColin Finck }
2337