2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 * Copyright 2005 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
32 #include "wine/debug.h"
36 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msi);
45 * This module will be all the helper functions for registry access by the
48 static const WCHAR szUserFeatures_fmt[] = {
49 'S','o','f','t','w','a','r','e','\\',
50 'M','i','c','r','o','s','o','f','t','\\',
51 'I','n','s','t','a','l','l','e','r','\\',
52 'F','e','a','t','u','r','e','s','\\',
55 static const WCHAR szInstaller_Features[] = {
56 'S','o','f','t','w','a','r','e','\\',
57 'M','i','c','r','o','s','o','f','t','\\',
58 'W','i','n','d','o','w','s','\\',
59 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
60 'I','n','s','t','a','l','l','e','r','\\',
61 'F','e','a','t','u','r','e','s',0 };
63 static const WCHAR szUserDataFeatures_fmt[] = {
64 'S','o','f','t','w','a','r','e','\\',
65 'M','i','c','r','o','s','o','f','t','\\',
66 'W','i','n','d','o','w','s','\\',
67 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
68 'I','n','s','t','a','l','l','e','r','\\',
69 'U','s','e','r','D','a','t','a','\\',
70 '%','s','\\','P','r','o','d','u','c','t','s','\\',
71 '%','s','\\','F','e','a','t','u','r','e','s',0};
73 static const WCHAR szInstaller_Features_fmt[] = {
74 'S','o','f','t','w','a','r','e','\\',
75 'M','i','c','r','o','s','o','f','t','\\',
76 'W','i','n','d','o','w','s','\\',
77 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
78 'I','n','s','t','a','l','l','e','r','\\',
79 'F','e','a','t','u','r','e','s','\\',
82 static const WCHAR szInstaller_Components[] = {
83 'S','o','f','t','w','a','r','e','\\',
84 'M','i','c','r','o','s','o','f','t','\\',
85 'W','i','n','d','o','w','s','\\',
86 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
87 'I','n','s','t','a','l','l','e','r','\\',
88 'C','o','m','p','o','n','e','n','t','s',0 };
90 static const WCHAR szInstaller_Components_fmt[] = {
91 'S','o','f','t','w','a','r','e','\\',
92 'M','i','c','r','o','s','o','f','t','\\',
93 'W','i','n','d','o','w','s','\\',
94 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
95 'I','n','s','t','a','l','l','e','r','\\',
96 'C','o','m','p','o','n','e','n','t','s','\\',
99 static const WCHAR szUser_Components_fmt[] = {
100 'S','o','f','t','w','a','r','e','\\',
101 'M','i','c','r','o','s','o','f','t','\\',
102 'I','n','s','t','a','l','l','e','r','\\',
103 'C','o','m','p','o','n','e','n','t','s','\\',
106 static const WCHAR szUserDataComp_fmt[] = {
107 'S','o','f','t','w','a','r','e','\\',
108 'M','i','c','r','o','s','o','f','t','\\',
109 'W','i','n','d','o','w','s','\\',
110 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
111 'I','n','s','t','a','l','l','e','r','\\',
112 'U','s','e','r','D','a','t','a','\\',
113 '%','s','\\','C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
115 static const WCHAR szUninstall_fmt[] = {
116 'S','o','f','t','w','a','r','e','\\',
117 'M','i','c','r','o','s','o','f','t','\\',
118 'W','i','n','d','o','w','s','\\',
119 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
120 'U','n','i','n','s','t','a','l','l','\\',
123 static const WCHAR szUserProduct_fmt[] = {
124 'S','o','f','t','w','a','r','e','\\',
125 'M','i','c','r','o','s','o','f','t','\\',
126 'I','n','s','t','a','l','l','e','r','\\',
127 'P','r','o','d','u','c','t','s','\\',
130 static const WCHAR szUserPatch_fmt[] = {
131 'S','o','f','t','w','a','r','e','\\',
132 'M','i','c','r','o','s','o','f','t','\\',
133 'I','n','s','t','a','l','l','e','r','\\',
134 'P','a','t','c','h','e','s','\\',
137 static const WCHAR szInstaller_Products[] = {
138 'S','o','f','t','w','a','r','e','\\',
139 'M','i','c','r','o','s','o','f','t','\\',
140 'W','i','n','d','o','w','s','\\',
141 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
142 'I','n','s','t','a','l','l','e','r','\\',
143 'P','r','o','d','u','c','t','s',0};
145 static const WCHAR szInstaller_Products_fmt[] = {
146 'S','o','f','t','w','a','r','e','\\',
147 'M','i','c','r','o','s','o','f','t','\\',
148 'W','i','n','d','o','w','s','\\',
149 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
150 'I','n','s','t','a','l','l','e','r','\\',
151 'P','r','o','d','u','c','t','s','\\',
154 static const WCHAR szInstaller_Patches_fmt[] = {
155 'S','o','f','t','w','a','r','e','\\',
156 'M','i','c','r','o','s','o','f','t','\\',
157 'W','i','n','d','o','w','s','\\',
158 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
159 'I','n','s','t','a','l','l','e','r','\\',
160 'P','a','t','c','h','e','s','\\',
163 static const WCHAR szInstaller_UpgradeCodes_fmt[] = {
164 'S','o','f','t','w','a','r','e','\\',
165 'M','i','c','r','o','s','o','f','t','\\',
166 'W','i','n','d','o','w','s','\\',
167 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
168 'I','n','s','t','a','l','l','e','r','\\',
169 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
172 static const WCHAR szInstaller_UserUpgradeCodes_fmt[] = {
173 'S','o','f','t','w','a','r','e','\\',
174 'M','i','c','r','o','s','o','f','t','\\',
175 'I','n','s','t','a','l','l','e','r','\\',
176 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
179 static const WCHAR szUserDataProd_fmt[] = {
180 'S','o','f','t','w','a','r','e','\\',
181 'M','i','c','r','o','s','o','f','t','\\',
182 'W','i','n','d','o','w','s','\\',
183 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
184 'I','n','s','t','a','l','l','e','r','\\',
185 'U','s','e','r','D','a','t','a','\\',
186 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
188 static const WCHAR szInstallProperties_fmt[] = {
189 'S','o','f','t','w','a','r','e','\\',
190 'M','i','c','r','o','s','o','f','t','\\',
191 'W','i','n','d','o','w','s','\\',
192 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
193 'I','n','s','t','a','l','l','e','r','\\',
194 'U','s','e','r','D','a','t','a','\\',
195 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
196 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
199 #define SQUISH_GUID_SIZE 33
201 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
217 out[n++] = in[17+i*2];
218 out[n++] = in[16+i*2];
223 out[n++] = in[17+i*2];
224 out[n++] = in[16+i*2];
231 BOOL squash_guid(LPCWSTR in, LPWSTR out)
238 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
252 out[17+i*2] = in[n++];
253 out[16+i*2] = in[n++];
258 out[17+i*2] = in[n++];
259 out[16+i*2] = in[n++];
266 /* tables for encoding and decoding base85 */
267 static const unsigned char table_dec85[0x80] = {
268 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
269 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
270 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
271 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
272 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
273 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
274 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
275 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
278 static const char table_enc85[] =
279 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
280 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
284 * Converts a base85 encoded guid into a GUID pointer
285 * Base85 encoded GUIDs should be 20 characters long.
287 * returns TRUE if successful, FALSE if not
289 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
291 DWORD i, val = 0, base = 1, *p;
297 for( i=0; i<20; i++ )
304 val += table_dec85[str[i]] * base;
307 if( table_dec85[str[i]] == 0xff )
317 * Encodes a base85 guid given a GUID pointer
318 * Caller should provide a 21 character buffer for the encoded string.
320 * returns TRUE if successful, FALSE if not
322 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
324 unsigned int x, *p, i;
326 p = (unsigned int*) guid;
330 *str++ = table_enc85[x%85];
332 *str++ = table_enc85[x%85];
334 *str++ = table_enc85[x%85];
336 *str++ = table_enc85[x%85];
338 *str++ = table_enc85[x%85];
345 DWORD msi_version_str_to_dword(LPCWSTR p)
347 DWORD major, minor = 0, build = 0, version = 0;
358 p = strchrW(p+1, '.');
363 return MAKELONG(build, MAKEWORD(minor, major));
366 LPWSTR msi_version_dword_to_str(DWORD version)
368 const WCHAR fmt[] = { '%','u','.','%','u','.','%','u',0 };
369 LPWSTR str = msi_alloc(20);
371 (version&0xff000000)>>24,
372 (version&0x00ff0000)>>16,
377 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
379 DWORD len = value ? (lstrlenW(value) + 1) * sizeof (WCHAR) : 0;
380 return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
383 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
386 while (*p) p += lstrlenW(p) + 1;
387 return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
388 (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
391 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
393 return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
396 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
401 r = RegCreateKeyW( hkey, path, &hsubkey );
402 if (r != ERROR_SUCCESS)
404 r = msi_reg_set_val_str( hsubkey, name, val );
405 RegCloseKey( hsubkey );
409 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
415 r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
416 if (r != ERROR_SUCCESS)
419 len += sizeof (WCHAR);
420 val = msi_alloc( len );
424 RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
428 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
430 DWORD type, len = sizeof (DWORD);
431 LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
432 return r == ERROR_SUCCESS && type == REG_DWORD;
435 static UINT get_user_sid(LPWSTR *usersid)
442 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
443 return ERROR_FUNCTION_FAILED;
446 if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size))
447 return ERROR_FUNCTION_FAILED;
449 user = (PTOKEN_USER)buf;
450 if (!ConvertSidToStringSidW(user->User.Sid, usersid))
451 return ERROR_FUNCTION_FAILED;
453 return ERROR_SUCCESS;
456 UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
459 WCHAR keypath[0x200];
460 TRACE("%s\n",debugstr_w(szProduct));
462 sprintfW(keypath,szUninstall_fmt,szProduct);
465 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
467 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
472 UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
475 WCHAR squished_pc[GUID_SIZE];
476 WCHAR keypath[0x200];
478 TRACE("%s\n",debugstr_w(szProduct));
479 if (!squash_guid(szProduct,squished_pc))
480 return ERROR_FUNCTION_FAILED;
481 TRACE("squished (%s)\n", debugstr_w(squished_pc));
483 sprintfW(keypath,szUserProduct_fmt,squished_pc);
486 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
488 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
493 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
495 WCHAR squished_pc[GUID_SIZE];
496 WCHAR keypath[0x200];
498 TRACE("%s\n",debugstr_w(szProduct));
499 if (!squash_guid(szProduct,squished_pc))
500 return ERROR_FUNCTION_FAILED;
501 TRACE("squished (%s)\n", debugstr_w(squished_pc));
503 sprintfW(keypath,szUserProduct_fmt,squished_pc);
505 return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
508 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
511 WCHAR squished_pc[GUID_SIZE];
512 WCHAR keypath[0x200];
514 TRACE("%s\n",debugstr_w(szPatch));
515 if (!squash_guid(szPatch,squished_pc))
516 return ERROR_FUNCTION_FAILED;
517 TRACE("squished (%s)\n", debugstr_w(squished_pc));
519 sprintfW(keypath,szUserPatch_fmt,squished_pc);
522 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
524 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
529 UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
532 WCHAR squished_pc[GUID_SIZE];
533 WCHAR keypath[0x200];
535 TRACE("%s\n",debugstr_w(szProduct));
536 if (!squash_guid(szProduct,squished_pc))
537 return ERROR_FUNCTION_FAILED;
538 TRACE("squished (%s)\n", debugstr_w(squished_pc));
540 sprintfW(keypath,szUserFeatures_fmt,squished_pc);
543 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
545 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
550 UINT MSIREG_OpenFeatures(HKEY* key)
552 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Features,key);
555 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
558 WCHAR squished_pc[GUID_SIZE];
559 WCHAR keypath[0x200];
561 TRACE("%s\n",debugstr_w(szProduct));
562 if (!squash_guid(szProduct,squished_pc))
563 return ERROR_FUNCTION_FAILED;
564 TRACE("squished (%s)\n", debugstr_w(squished_pc));
566 sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
569 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
571 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
576 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
579 WCHAR squished_pc[GUID_SIZE];
580 WCHAR keypath[0x200];
583 TRACE("%s\n", debugstr_w(szProduct));
584 if (!squash_guid(szProduct, squished_pc))
585 return ERROR_FUNCTION_FAILED;
586 TRACE("squished (%s)\n", debugstr_w(squished_pc));
588 rc = get_user_sid(&usersid);
589 if (rc != ERROR_SUCCESS || !usersid)
591 ERR("Failed to retrieve user SID: %d\n", rc);
595 sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
598 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
600 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
606 UINT MSIREG_OpenComponents(HKEY* key)
608 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key);
611 UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
614 WCHAR squished_cc[GUID_SIZE];
615 WCHAR keypath[0x200];
617 TRACE("%s\n",debugstr_w(szComponent));
618 if (!squash_guid(szComponent,squished_cc))
619 return ERROR_FUNCTION_FAILED;
620 TRACE("squished (%s)\n", debugstr_w(squished_cc));
622 sprintfW(keypath,szInstaller_Components_fmt,squished_cc);
625 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
627 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
632 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
635 WCHAR squished_cc[GUID_SIZE];
636 WCHAR keypath[0x200];
638 TRACE("%s\n",debugstr_w(szComponent));
639 if (!squash_guid(szComponent,squished_cc))
640 return ERROR_FUNCTION_FAILED;
641 TRACE("squished (%s)\n", debugstr_w(squished_cc));
643 sprintfW(keypath,szUser_Components_fmt,squished_cc);
646 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
648 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
653 UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create)
656 WCHAR comp[GUID_SIZE];
657 WCHAR keypath[0x200];
660 TRACE("%s\n", debugstr_w(szComponent));
661 if (!squash_guid(szComponent, comp))
662 return ERROR_FUNCTION_FAILED;
663 TRACE("squished (%s)\n", debugstr_w(comp));
665 rc = get_user_sid(&usersid);
666 if (rc != ERROR_SUCCESS || !usersid)
668 ERR("Failed to retrieve user SID: %d\n", rc);
672 sprintfW(keypath, szUserDataComp_fmt, usersid, comp);
675 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
677 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
683 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
686 WCHAR squished_pc[GUID_SIZE];
687 WCHAR keypath[0x200];
690 TRACE("%s\n", debugstr_w(szProduct));
691 if (!squash_guid(szProduct, squished_pc))
692 return ERROR_FUNCTION_FAILED;
693 TRACE("squished (%s)\n", debugstr_w(squished_pc));
695 rc = get_user_sid(&usersid);
696 if (rc != ERROR_SUCCESS || !usersid)
698 ERR("Failed to retrieve user SID: %d\n", rc);
702 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
705 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
707 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
713 UINT MSIREG_OpenInstallPropertiesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
716 WCHAR squished_pc[GUID_SIZE];
717 WCHAR keypath[0x200];
720 TRACE("%s\n", debugstr_w(szProduct));
721 if (!squash_guid(szProduct, squished_pc))
722 return ERROR_FUNCTION_FAILED;
723 TRACE("squished (%s)\n", debugstr_w(squished_pc));
725 rc = get_user_sid(&usersid);
726 if (rc != ERROR_SUCCESS || !usersid)
728 ERR("Failed to retrieve user SID: %d\n", rc);
732 sprintfW(keypath, szInstallProperties_fmt, usersid, squished_pc);
735 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
737 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
743 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
746 WCHAR squished_pc[GUID_SIZE];
747 WCHAR keypath[0x200];
750 TRACE("%s\n", debugstr_w(szProduct));
751 if (!squash_guid(szProduct, squished_pc))
752 return ERROR_FUNCTION_FAILED;
753 TRACE("squished (%s)\n", debugstr_w(squished_pc));
755 rc = get_user_sid(&usersid);
756 if (rc != ERROR_SUCCESS || !usersid)
758 ERR("Failed to retrieve user SID: %d\n", rc);
762 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
765 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
768 UINT MSIREG_OpenProducts(HKEY* key)
770 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key);
773 UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
776 WCHAR squished_pc[GUID_SIZE];
777 WCHAR keypath[0x200];
779 TRACE("%s\n",debugstr_w(szProduct));
780 if (!squash_guid(szProduct,squished_pc))
781 return ERROR_FUNCTION_FAILED;
782 TRACE("squished (%s)\n", debugstr_w(squished_pc));
784 sprintfW(keypath,szInstaller_Products_fmt,squished_pc);
787 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
789 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
794 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
796 WCHAR squished_pc[GUID_SIZE];
797 WCHAR keypath[0x200];
799 TRACE("%s\n", debugstr_w(szProduct));
800 if (!squash_guid(szProduct, squished_pc))
801 return ERROR_FUNCTION_FAILED;
802 TRACE("squished (%s)\n", debugstr_w(squished_pc));
804 sprintfW(keypath, szInstaller_Products_fmt, squished_pc);
806 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
809 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
812 WCHAR squished_pc[GUID_SIZE];
813 WCHAR keypath[0x200];
815 TRACE("%s\n",debugstr_w(szPatch));
816 if (!squash_guid(szPatch,squished_pc))
817 return ERROR_FUNCTION_FAILED;
818 TRACE("squished (%s)\n", debugstr_w(squished_pc));
820 sprintfW(keypath,szInstaller_Patches_fmt,squished_pc);
823 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
825 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
830 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
833 WCHAR squished_pc[GUID_SIZE];
834 WCHAR keypath[0x200];
836 TRACE("%s\n",debugstr_w(szUpgradeCode));
837 if (!squash_guid(szUpgradeCode,squished_pc))
838 return ERROR_FUNCTION_FAILED;
839 TRACE("squished (%s)\n", debugstr_w(squished_pc));
841 sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
844 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
846 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
851 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
854 WCHAR squished_pc[GUID_SIZE];
855 WCHAR keypath[0x200];
857 TRACE("%s\n",debugstr_w(szUpgradeCode));
858 if (!squash_guid(szUpgradeCode,squished_pc))
859 return ERROR_FUNCTION_FAILED;
860 TRACE("squished (%s)\n", debugstr_w(squished_pc));
862 sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
865 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
867 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
873 /*************************************************************************
874 * MsiDecomposeDescriptorW [MSI.@]
876 * Decomposes an MSI descriptor into product, feature and component parts.
877 * An MSI descriptor is a string of the form:
878 * [base 85 guid] [feature code] '>' [base 85 guid]
881 * szDescriptor [I] the descriptor to decompose
882 * szProduct [O] buffer of MAX_FEATURE_CHARS+1 for the product guid
883 * szFeature [O] buffer of MAX_FEATURE_CHARS+1 for the feature code
884 * szComponent [O] buffer of MAX_FEATURE_CHARS+1 for the component guid
885 * pUsed [O] the length of the descriptor
888 * ERROR_SUCCESS if everything worked correctly
889 * ERROR_INVALID_PARAMETER if the descriptor was invalid
892 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
893 LPWSTR szFeature, LPWSTR szComponent, DWORD *pUsed )
897 GUID product, component;
899 TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
900 szFeature, szComponent, pUsed);
902 r = decode_base85_guid( szDescriptor, &product );
904 return ERROR_INVALID_PARAMETER;
906 TRACE("product %s\n", debugstr_guid( &product ));
908 p = strchrW(&szDescriptor[20],'>');
910 return ERROR_INVALID_PARAMETER;
912 len = (p - &szDescriptor[20]);
913 if( len > MAX_FEATURE_CHARS )
914 return ERROR_INVALID_PARAMETER;
916 TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
918 r = decode_base85_guid( p+1, &component );
920 return ERROR_INVALID_PARAMETER;
922 TRACE("component %s\n", debugstr_guid( &component ));
925 StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
927 StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
930 memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
933 len = ( &p[21] - szDescriptor );
935 TRACE("length = %d\n", len);
938 return ERROR_SUCCESS;
941 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
942 LPSTR szFeature, LPSTR szComponent, DWORD *pUsed )
944 WCHAR product[MAX_FEATURE_CHARS+1];
945 WCHAR feature[MAX_FEATURE_CHARS+1];
946 WCHAR component[MAX_FEATURE_CHARS+1];
947 LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
950 TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
951 szFeature, szComponent, pUsed);
953 str = strdupAtoW( szDescriptor );
954 if( szDescriptor && !str )
955 return ERROR_OUTOFMEMORY;
964 r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
966 if (r == ERROR_SUCCESS)
968 WideCharToMultiByte( CP_ACP, 0, p, -1,
969 szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
970 WideCharToMultiByte( CP_ACP, 0, f, -1,
971 szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
972 WideCharToMultiByte( CP_ACP, 0, c, -1,
973 szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
981 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
984 WCHAR szwGuid[GUID_SIZE];
986 TRACE("%d %p\n", index, lpguid);
989 return ERROR_INVALID_PARAMETER;
990 r = MsiEnumProductsW(index, szwGuid);
991 if( r == ERROR_SUCCESS )
992 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
997 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
999 HKEY hkeyProducts = 0;
1001 WCHAR szKeyName[SQUISH_GUID_SIZE];
1003 TRACE("%d %p\n", index, lpguid);
1006 return ERROR_INVALID_PARAMETER;
1008 r = MSIREG_OpenProducts(&hkeyProducts);
1009 if( r != ERROR_SUCCESS )
1010 return ERROR_NO_MORE_ITEMS;
1012 r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
1013 if( r == ERROR_SUCCESS )
1014 unsquash_guid(szKeyName, lpguid);
1015 RegCloseKey(hkeyProducts);
1020 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
1021 LPSTR szFeature, LPSTR szParent)
1024 WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
1025 LPWSTR szwProduct = NULL;
1027 TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
1031 szwProduct = strdupAtoW( szProduct );
1033 return ERROR_OUTOFMEMORY;
1036 r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
1037 if( r == ERROR_SUCCESS )
1039 WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
1040 szFeature, GUID_SIZE, NULL, NULL);
1041 WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
1042 szParent, GUID_SIZE, NULL, NULL);
1045 msi_free( szwProduct);
1050 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
1051 LPWSTR szFeature, LPWSTR szParent)
1053 HKEY hkeyProduct = 0;
1056 TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
1059 return ERROR_INVALID_PARAMETER;
1061 r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE);
1062 if( r != ERROR_SUCCESS )
1063 return ERROR_NO_MORE_ITEMS;
1066 r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1067 RegCloseKey(hkeyProduct);
1072 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1075 WCHAR szwGuid[GUID_SIZE];
1077 TRACE("%d %p\n", index, lpguid);
1079 r = MsiEnumComponentsW(index, szwGuid);
1080 if( r == ERROR_SUCCESS )
1081 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1086 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1088 HKEY hkeyComponents = 0;
1090 WCHAR szKeyName[SQUISH_GUID_SIZE];
1092 TRACE("%d %p\n", index, lpguid);
1094 r = MSIREG_OpenComponents(&hkeyComponents);
1095 if( r != ERROR_SUCCESS )
1096 return ERROR_NO_MORE_ITEMS;
1098 r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
1099 if( r == ERROR_SUCCESS )
1100 unsquash_guid(szKeyName, lpguid);
1101 RegCloseKey(hkeyComponents);
1106 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1109 WCHAR szwProduct[GUID_SIZE];
1110 LPWSTR szwComponent = NULL;
1112 TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
1116 szwComponent = strdupAtoW( szComponent );
1118 return ERROR_OUTOFMEMORY;
1121 r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1122 if( r == ERROR_SUCCESS )
1124 WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1125 szProduct, GUID_SIZE, NULL, NULL);
1128 msi_free( szwComponent);
1133 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1137 WCHAR szValName[SQUISH_GUID_SIZE];
1139 TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
1141 r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE);
1142 if( r != ERROR_SUCCESS )
1143 return ERROR_NO_MORE_ITEMS;
1145 sz = SQUISH_GUID_SIZE;
1146 r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1147 if( r == ERROR_SUCCESS )
1148 unsquash_guid(szValName, szProduct);
1150 RegCloseKey(hkeyComp);
1155 static UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
1156 awstring *lpQualBuf, DWORD* pcchQual,
1157 awstring *lpAppBuf, DWORD* pcchAppBuf )
1159 DWORD name_sz, val_sz, name_max, val_max, type, ofs;
1160 LPWSTR name = NULL, val = NULL;
1164 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1165 lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
1168 return ERROR_INVALID_PARAMETER;
1170 r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1171 if (r != ERROR_SUCCESS)
1172 return ERROR_UNKNOWN_COMPONENT;
1174 /* figure out how big the name is we want to return */
1176 r = ERROR_OUTOFMEMORY;
1177 name = msi_alloc( name_max * sizeof(WCHAR) );
1182 r = ERROR_OUTOFMEMORY;
1183 val = msi_alloc( val_max );
1187 /* loop until we allocate enough memory */
1192 r = RegEnumValueW( key, iIndex, name, &name_sz,
1193 NULL, &type, (LPBYTE)val, &val_sz );
1194 if (r == ERROR_SUCCESS)
1196 if (r != ERROR_MORE_DATA)
1199 if (type != REG_MULTI_SZ)
1201 ERR("component data has wrong type (%d)\n", type);
1205 r = ERROR_OUTOFMEMORY;
1206 if ((name_sz+1) >= name_max)
1210 name = msi_alloc( name_max * sizeof (WCHAR) );
1215 if (val_sz > val_max)
1217 val_max = val_sz + sizeof (WCHAR);
1219 val = msi_alloc( val_max * sizeof (WCHAR) );
1224 ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
1229 r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1230 if (r != ERROR_SUCCESS)
1233 TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1235 r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
1236 r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
1238 if (r2 != ERROR_SUCCESS)
1249 /*************************************************************************
1250 * MsiEnumComponentQualifiersA [MSI.@]
1252 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
1253 LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
1254 LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
1256 awstring qual, appdata;
1260 TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
1261 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1262 pcchApplicationDataBuf);
1264 comp = strdupAtoW( szComponent );
1265 if (szComponent && !comp)
1266 return ERROR_OUTOFMEMORY;
1268 qual.unicode = FALSE;
1269 qual.str.a = lpQualifierBuf;
1271 appdata.unicode = FALSE;
1272 appdata.str.a = lpApplicationDataBuf;
1274 r = MSI_EnumComponentQualifiers( comp, iIndex,
1275 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1280 /*************************************************************************
1281 * MsiEnumComponentQualifiersW [MSI.@]
1283 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
1284 LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
1285 LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
1287 awstring qual, appdata;
1289 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1290 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1291 pcchApplicationDataBuf);
1293 qual.unicode = TRUE;
1294 qual.str.w = lpQualifierBuf;
1296 appdata.unicode = TRUE;
1297 appdata.str.w = lpApplicationDataBuf;
1299 return MSI_EnumComponentQualifiers( szComponent, iIndex,
1300 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1303 /*************************************************************************
1304 * MsiEnumRelatedProductsW [MSI.@]
1307 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
1308 DWORD iProductIndex, LPWSTR lpProductBuf)
1312 DWORD dwSize = SQUISH_GUID_SIZE;
1313 WCHAR szKeyName[SQUISH_GUID_SIZE];
1315 TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
1316 iProductIndex, lpProductBuf);
1318 if (NULL == szUpgradeCode)
1319 return ERROR_INVALID_PARAMETER;
1320 if (NULL == lpProductBuf)
1321 return ERROR_INVALID_PARAMETER;
1323 r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1324 if (r != ERROR_SUCCESS)
1325 return ERROR_NO_MORE_ITEMS;
1327 r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1328 if( r == ERROR_SUCCESS )
1329 unsquash_guid(szKeyName, lpProductBuf);
1335 /*************************************************************************
1336 * MsiEnumRelatedProductsA [MSI.@]
1339 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
1340 DWORD iProductIndex, LPSTR lpProductBuf)
1342 LPWSTR szwUpgradeCode = NULL;
1343 WCHAR productW[GUID_SIZE];
1346 TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
1347 iProductIndex, lpProductBuf);
1351 szwUpgradeCode = strdupAtoW( szUpgradeCode );
1352 if( !szwUpgradeCode )
1353 return ERROR_OUTOFMEMORY;
1356 r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1357 iProductIndex, productW );
1358 if (r == ERROR_SUCCESS)
1360 WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1361 lpProductBuf, GUID_SIZE, NULL, NULL );
1363 msi_free( szwUpgradeCode);
1367 /***********************************************************************
1368 * MsiEnumPatchesA [MSI.@]
1370 UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
1371 LPSTR lpPatchBuf, LPSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1373 FIXME("%s %d %p %p %p\n", debugstr_a(szProduct),
1374 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1375 return ERROR_NO_MORE_ITEMS;
1378 /***********************************************************************
1379 * MsiEnumPatchesW [MSI.@]
1381 UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
1382 LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1384 FIXME("%s %d %p %p %p\n", debugstr_w(szProduct),
1385 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1386 return ERROR_NO_MORE_ITEMS;
1389 UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
1390 DWORD dwContext, DWORD dwIndex, LPSTR szInstalledProductCode,
1391 MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
1393 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
1394 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1396 return ERROR_NO_MORE_ITEMS;
1399 UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
1400 DWORD dwContext, DWORD dwIndex, LPWSTR szInstalledProductCode,
1401 MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
1403 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
1404 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1406 return ERROR_NO_MORE_ITEMS;