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 szUninstall_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 'U','n','i','n','s','t','a','l','l','\\',
114 static const WCHAR szUserProduct_fmt[] = {
115 'S','o','f','t','w','a','r','e','\\',
116 'M','i','c','r','o','s','o','f','t','\\',
117 'I','n','s','t','a','l','l','e','r','\\',
118 'P','r','o','d','u','c','t','s','\\',
121 static const WCHAR szUserPatch_fmt[] = {
122 'S','o','f','t','w','a','r','e','\\',
123 'M','i','c','r','o','s','o','f','t','\\',
124 'I','n','s','t','a','l','l','e','r','\\',
125 'P','a','t','c','h','e','s','\\',
128 static const WCHAR szInstaller_Products[] = {
129 'S','o','f','t','w','a','r','e','\\',
130 'M','i','c','r','o','s','o','f','t','\\',
131 'W','i','n','d','o','w','s','\\',
132 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
133 'I','n','s','t','a','l','l','e','r','\\',
134 'P','r','o','d','u','c','t','s',0};
136 static const WCHAR szInstaller_Products_fmt[] = {
137 'S','o','f','t','w','a','r','e','\\',
138 'M','i','c','r','o','s','o','f','t','\\',
139 'W','i','n','d','o','w','s','\\',
140 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
141 'I','n','s','t','a','l','l','e','r','\\',
142 'P','r','o','d','u','c','t','s','\\',
145 static const WCHAR szInstaller_Patches_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','a','t','c','h','e','s','\\',
154 static const WCHAR szInstaller_UpgradeCodes_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 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
163 static const WCHAR szInstaller_UserUpgradeCodes_fmt[] = {
164 'S','o','f','t','w','a','r','e','\\',
165 'M','i','c','r','o','s','o','f','t','\\',
166 'I','n','s','t','a','l','l','e','r','\\',
167 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
170 static const WCHAR szUserDataProd_fmt[] = {
171 'S','o','f','t','w','a','r','e','\\',
172 'M','i','c','r','o','s','o','f','t','\\',
173 'W','i','n','d','o','w','s','\\',
174 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
175 'I','n','s','t','a','l','l','e','r','\\',
176 'U','s','e','r','D','a','t','a','\\',
177 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
179 static const WCHAR szInstallProperties_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','\\',
187 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
190 #define SQUISH_GUID_SIZE 33
192 BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
208 out[n++] = in[17+i*2];
209 out[n++] = in[16+i*2];
214 out[n++] = in[17+i*2];
215 out[n++] = in[16+i*2];
222 BOOL squash_guid(LPCWSTR in, LPWSTR out)
227 if (FAILED(CLSIDFromString((LPOLESTR)in, &guid)))
241 out[17+i*2] = in[n++];
242 out[16+i*2] = in[n++];
247 out[17+i*2] = in[n++];
248 out[16+i*2] = in[n++];
255 /* tables for encoding and decoding base85 */
256 static const unsigned char table_dec85[0x80] = {
257 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
258 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
259 0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,
260 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,
261 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
262 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,
263 0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,
264 0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff,
267 static const char table_enc85[] =
268 "!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNO"
269 "PQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwx"
273 * Converts a base85 encoded guid into a GUID pointer
274 * Base85 encoded GUIDs should be 20 characters long.
276 * returns TRUE if successful, FALSE if not
278 BOOL decode_base85_guid( LPCWSTR str, GUID *guid )
280 DWORD i, val = 0, base = 1, *p;
286 for( i=0; i<20; i++ )
293 val += table_dec85[str[i]] * base;
296 if( table_dec85[str[i]] == 0xff )
306 * Encodes a base85 guid given a GUID pointer
307 * Caller should provide a 21 character buffer for the encoded string.
309 * returns TRUE if successful, FALSE if not
311 BOOL encode_base85_guid( GUID *guid, LPWSTR str )
313 unsigned int x, *p, i;
315 p = (unsigned int*) guid;
319 *str++ = table_enc85[x%85];
321 *str++ = table_enc85[x%85];
323 *str++ = table_enc85[x%85];
325 *str++ = table_enc85[x%85];
327 *str++ = table_enc85[x%85];
334 DWORD msi_version_str_to_dword(LPCWSTR p)
336 DWORD major, minor = 0, build = 0, version = 0;
347 p = strchrW(p+1, '.');
352 return MAKELONG(build, MAKEWORD(minor, major));
355 LPWSTR msi_version_dword_to_str(DWORD version)
357 const WCHAR fmt[] = { '%','u','.','%','u','.','%','u',0 };
358 LPWSTR str = msi_alloc(20);
360 (version&0xff000000)>>24,
361 (version&0x00ff0000)>>16,
366 LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
368 DWORD len = value ? (lstrlenW(value) + 1) * sizeof (WCHAR) : 0;
369 return RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)value, len );
372 LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value )
375 while (*p) p += lstrlenW(p) + 1;
376 return RegSetValueExW( hkey, name, 0, REG_MULTI_SZ,
377 (const BYTE *)value, (p + 1 - value) * sizeof(WCHAR) );
380 LONG msi_reg_set_val_dword( HKEY hkey, LPCWSTR name, DWORD val )
382 return RegSetValueExW( hkey, name, 0, REG_DWORD, (LPBYTE)&val, sizeof (DWORD) );
385 LONG msi_reg_set_subkey_val( HKEY hkey, LPCWSTR path, LPCWSTR name, LPCWSTR val )
390 r = RegCreateKeyW( hkey, path, &hsubkey );
391 if (r != ERROR_SUCCESS)
393 r = msi_reg_set_val_str( hsubkey, name, val );
394 RegCloseKey( hsubkey );
398 LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name )
404 r = RegQueryValueExW(hkey, name, NULL, NULL, NULL, &len);
405 if (r != ERROR_SUCCESS)
408 len += sizeof (WCHAR);
409 val = msi_alloc( len );
413 RegQueryValueExW(hkey, name, NULL, NULL, (LPBYTE) val, &len);
417 BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val)
419 DWORD type, len = sizeof (DWORD);
420 LONG r = RegQueryValueExW(hkey, name, NULL, &type, (LPBYTE) val, &len);
421 return r == ERROR_SUCCESS && type == REG_DWORD;
424 static UINT get_user_sid(LPWSTR *usersid)
431 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
432 return ERROR_FUNCTION_FAILED;
435 if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size))
436 return ERROR_FUNCTION_FAILED;
438 user = (PTOKEN_USER)buf;
439 if (!ConvertSidToStringSidW(user->User.Sid, usersid))
440 return ERROR_FUNCTION_FAILED;
442 return ERROR_SUCCESS;
445 UINT MSIREG_OpenUninstallKey(LPCWSTR szProduct, HKEY* key, BOOL create)
448 WCHAR keypath[0x200];
449 TRACE("%s\n",debugstr_w(szProduct));
451 sprintfW(keypath,szUninstall_fmt,szProduct);
454 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
456 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
461 UINT MSIREG_OpenUserProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
464 WCHAR squished_pc[GUID_SIZE];
465 WCHAR keypath[0x200];
467 TRACE("%s\n",debugstr_w(szProduct));
468 squash_guid(szProduct,squished_pc);
469 TRACE("squished (%s)\n", debugstr_w(squished_pc));
471 sprintfW(keypath,szUserProduct_fmt,squished_pc);
474 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
476 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
481 UINT MSIREG_DeleteUserProductKey(LPCWSTR szProduct)
483 WCHAR squished_pc[GUID_SIZE];
484 WCHAR keypath[0x200];
486 TRACE("%s\n",debugstr_w(szProduct));
487 squash_guid(szProduct,squished_pc);
488 TRACE("squished (%s)\n", debugstr_w(squished_pc));
490 sprintfW(keypath,szUserProduct_fmt,squished_pc);
492 return RegDeleteTreeW(HKEY_CURRENT_USER, keypath);
495 UINT MSIREG_OpenUserPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
498 WCHAR squished_pc[GUID_SIZE];
499 WCHAR keypath[0x200];
501 TRACE("%s\n",debugstr_w(szPatch));
502 squash_guid(szPatch,squished_pc);
503 TRACE("squished (%s)\n", debugstr_w(squished_pc));
505 sprintfW(keypath,szUserPatch_fmt,squished_pc);
508 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
510 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
515 UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
518 WCHAR squished_pc[GUID_SIZE];
519 WCHAR keypath[0x200];
521 TRACE("%s\n",debugstr_w(szProduct));
522 squash_guid(szProduct,squished_pc);
523 TRACE("squished (%s)\n", debugstr_w(squished_pc));
525 sprintfW(keypath,szUserFeatures_fmt,squished_pc);
528 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
530 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
535 UINT MSIREG_OpenFeatures(HKEY* key)
537 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Features,key);
540 UINT MSIREG_OpenFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create)
543 WCHAR squished_pc[GUID_SIZE];
544 WCHAR keypath[0x200];
546 TRACE("%s\n",debugstr_w(szProduct));
547 squash_guid(szProduct,squished_pc);
548 TRACE("squished (%s)\n", debugstr_w(squished_pc));
550 sprintfW(keypath,szInstaller_Features_fmt,squished_pc);
553 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
555 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
560 UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
563 WCHAR squished_pc[GUID_SIZE];
564 WCHAR keypath[0x200];
567 TRACE("%s\n", debugstr_w(szProduct));
568 squash_guid(szProduct, squished_pc);
569 TRACE("squished (%s)\n", debugstr_w(squished_pc));
571 rc = get_user_sid(&usersid);
572 if (rc != ERROR_SUCCESS || !usersid)
574 ERR("Failed to retrieve user SID: %d\n", rc);
578 sprintfW(keypath, szUserDataFeatures_fmt, usersid, squished_pc);
581 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
583 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
589 UINT MSIREG_OpenComponents(HKEY* key)
591 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Components,key);
594 UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
597 WCHAR squished_cc[GUID_SIZE];
598 WCHAR keypath[0x200];
600 TRACE("%s\n",debugstr_w(szComponent));
601 squash_guid(szComponent,squished_cc);
602 TRACE("squished (%s)\n", debugstr_w(squished_cc));
604 sprintfW(keypath,szInstaller_Components_fmt,squished_cc);
607 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
609 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
614 UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
617 WCHAR squished_cc[GUID_SIZE];
618 WCHAR keypath[0x200];
620 TRACE("%s\n",debugstr_w(szComponent));
621 squash_guid(szComponent,squished_cc);
622 TRACE("squished (%s)\n", debugstr_w(squished_cc));
624 sprintfW(keypath,szUser_Components_fmt,squished_cc);
627 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
629 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
634 UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
637 WCHAR squished_pc[GUID_SIZE];
638 WCHAR keypath[0x200];
641 TRACE("%s\n", debugstr_w(szProduct));
642 squash_guid(szProduct, squished_pc);
643 TRACE("squished (%s)\n", debugstr_w(squished_pc));
645 rc = get_user_sid(&usersid);
646 if (rc != ERROR_SUCCESS || !usersid)
648 ERR("Failed to retrieve user SID: %d\n", rc);
652 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
655 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
657 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
663 UINT MSIREG_OpenInstallPropertiesKey(LPCWSTR szProduct, HKEY *key, BOOL create)
666 WCHAR squished_pc[GUID_SIZE];
667 WCHAR keypath[0x200];
670 TRACE("%s\n", debugstr_w(szProduct));
671 squash_guid(szProduct, squished_pc);
672 TRACE("squished (%s)\n", debugstr_w(squished_pc));
674 rc = get_user_sid(&usersid);
675 if (rc != ERROR_SUCCESS || !usersid)
677 ERR("Failed to retrieve user SID: %d\n", rc);
681 sprintfW(keypath, szInstallProperties_fmt, usersid, squished_pc);
684 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
686 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
692 UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct)
695 WCHAR squished_pc[GUID_SIZE];
696 WCHAR keypath[0x200];
699 TRACE("%s\n", debugstr_w(szProduct));
700 squash_guid(szProduct, squished_pc);
701 TRACE("squished (%s)\n", debugstr_w(squished_pc));
703 rc = get_user_sid(&usersid);
704 if (rc != ERROR_SUCCESS || !usersid)
706 ERR("Failed to retrieve user SID: %d\n", rc);
710 sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
713 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
716 UINT MSIREG_OpenProducts(HKEY* key)
718 return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key);
721 UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
724 WCHAR squished_pc[GUID_SIZE];
725 WCHAR keypath[0x200];
727 TRACE("%s\n",debugstr_w(szProduct));
728 squash_guid(szProduct,squished_pc);
729 TRACE("squished (%s)\n", debugstr_w(squished_pc));
731 sprintfW(keypath,szInstaller_Products_fmt,squished_pc);
734 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
736 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
741 UINT MSIREG_DeleteProductKey(LPCWSTR szProduct)
743 WCHAR squished_pc[GUID_SIZE];
744 WCHAR keypath[0x200];
746 TRACE("%s\n", debugstr_w(szProduct));
747 squash_guid(szProduct, squished_pc);
748 TRACE("squished (%s)\n", debugstr_w(squished_pc));
750 sprintfW(keypath, szInstaller_Products_fmt, squished_pc);
752 return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath);
755 UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create)
758 WCHAR squished_pc[GUID_SIZE];
759 WCHAR keypath[0x200];
761 TRACE("%s\n",debugstr_w(szPatch));
762 squash_guid(szPatch,squished_pc);
763 TRACE("squished (%s)\n", debugstr_w(squished_pc));
765 sprintfW(keypath,szInstaller_Patches_fmt,squished_pc);
768 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
770 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
775 UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
778 WCHAR squished_pc[GUID_SIZE];
779 WCHAR keypath[0x200];
781 TRACE("%s\n",debugstr_w(szUpgradeCode));
782 squash_guid(szUpgradeCode,squished_pc);
783 TRACE("squished (%s)\n", debugstr_w(squished_pc));
785 sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
788 rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
790 rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
795 UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
798 WCHAR squished_pc[GUID_SIZE];
799 WCHAR keypath[0x200];
801 TRACE("%s\n",debugstr_w(szUpgradeCode));
802 squash_guid(szUpgradeCode,squished_pc);
803 TRACE("squished (%s)\n", debugstr_w(squished_pc));
805 sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
808 rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
810 rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
816 /*************************************************************************
817 * MsiDecomposeDescriptorW [MSI.@]
819 * Decomposes an MSI descriptor into product, feature and component parts.
820 * An MSI descriptor is a string of the form:
821 * [base 85 guid] [feature code] '>' [base 85 guid]
824 * szDescriptor [I] the descriptor to decompose
825 * szProduct [O] buffer of MAX_FEATURE_CHARS+1 for the product guid
826 * szFeature [O] buffer of MAX_FEATURE_CHARS+1 for the feature code
827 * szComponent [O] buffer of MAX_FEATURE_CHARS+1 for the component guid
828 * pUsed [O] the length of the descriptor
831 * ERROR_SUCCESS if everything worked correctly
832 * ERROR_INVALID_PARAMETER if the descriptor was invalid
835 UINT WINAPI MsiDecomposeDescriptorW( LPCWSTR szDescriptor, LPWSTR szProduct,
836 LPWSTR szFeature, LPWSTR szComponent, DWORD *pUsed )
840 GUID product, component;
842 TRACE("%s %p %p %p %p\n", debugstr_w(szDescriptor), szProduct,
843 szFeature, szComponent, pUsed);
845 r = decode_base85_guid( szDescriptor, &product );
847 return ERROR_INVALID_PARAMETER;
849 TRACE("product %s\n", debugstr_guid( &product ));
851 p = strchrW(&szDescriptor[20],'>');
853 return ERROR_INVALID_PARAMETER;
855 len = (p - &szDescriptor[20]);
856 if( len > MAX_FEATURE_CHARS )
857 return ERROR_INVALID_PARAMETER;
859 TRACE("feature %s\n", debugstr_wn( &szDescriptor[20], len ));
861 r = decode_base85_guid( p+1, &component );
863 return ERROR_INVALID_PARAMETER;
865 TRACE("component %s\n", debugstr_guid( &component ));
868 StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
870 StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
873 memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
876 len = ( &p[21] - szDescriptor );
878 TRACE("length = %d\n", len);
881 return ERROR_SUCCESS;
884 UINT WINAPI MsiDecomposeDescriptorA( LPCSTR szDescriptor, LPSTR szProduct,
885 LPSTR szFeature, LPSTR szComponent, DWORD *pUsed )
887 WCHAR product[MAX_FEATURE_CHARS+1];
888 WCHAR feature[MAX_FEATURE_CHARS+1];
889 WCHAR component[MAX_FEATURE_CHARS+1];
890 LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
893 TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
894 szFeature, szComponent, pUsed);
896 str = strdupAtoW( szDescriptor );
897 if( szDescriptor && !str )
898 return ERROR_OUTOFMEMORY;
907 r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
909 if (r == ERROR_SUCCESS)
911 WideCharToMultiByte( CP_ACP, 0, p, -1,
912 szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
913 WideCharToMultiByte( CP_ACP, 0, f, -1,
914 szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
915 WideCharToMultiByte( CP_ACP, 0, c, -1,
916 szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
924 UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
927 WCHAR szwGuid[GUID_SIZE];
929 TRACE("%d %p\n", index, lpguid);
932 return ERROR_INVALID_PARAMETER;
933 r = MsiEnumProductsW(index, szwGuid);
934 if( r == ERROR_SUCCESS )
935 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
940 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
942 HKEY hkeyProducts = 0;
944 WCHAR szKeyName[SQUISH_GUID_SIZE];
946 TRACE("%d %p\n", index, lpguid);
949 return ERROR_INVALID_PARAMETER;
951 r = MSIREG_OpenProducts(&hkeyProducts);
952 if( r != ERROR_SUCCESS )
953 return ERROR_NO_MORE_ITEMS;
955 r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
956 if( r == ERROR_SUCCESS )
957 unsquash_guid(szKeyName, lpguid);
958 RegCloseKey(hkeyProducts);
963 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
964 LPSTR szFeature, LPSTR szParent)
967 WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
968 LPWSTR szwProduct = NULL;
970 TRACE("%s %d %p %p\n", debugstr_a(szProduct), index, szFeature, szParent);
974 szwProduct = strdupAtoW( szProduct );
976 return ERROR_OUTOFMEMORY;
979 r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
980 if( r == ERROR_SUCCESS )
982 WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
983 szFeature, GUID_SIZE, NULL, NULL);
984 WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
985 szParent, GUID_SIZE, NULL, NULL);
988 msi_free( szwProduct);
993 UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
994 LPWSTR szFeature, LPWSTR szParent)
996 HKEY hkeyProduct = 0;
999 TRACE("%s %d %p %p\n", debugstr_w(szProduct), index, szFeature, szParent);
1002 return ERROR_INVALID_PARAMETER;
1004 r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE);
1005 if( r != ERROR_SUCCESS )
1006 return ERROR_NO_MORE_ITEMS;
1009 r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
1010 RegCloseKey(hkeyProduct);
1015 UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
1018 WCHAR szwGuid[GUID_SIZE];
1020 TRACE("%d %p\n", index, lpguid);
1022 r = MsiEnumComponentsW(index, szwGuid);
1023 if( r == ERROR_SUCCESS )
1024 WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
1029 UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
1031 HKEY hkeyComponents = 0;
1033 WCHAR szKeyName[SQUISH_GUID_SIZE];
1035 TRACE("%d %p\n", index, lpguid);
1037 r = MSIREG_OpenComponents(&hkeyComponents);
1038 if( r != ERROR_SUCCESS )
1039 return ERROR_NO_MORE_ITEMS;
1041 r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
1042 if( r == ERROR_SUCCESS )
1043 unsquash_guid(szKeyName, lpguid);
1044 RegCloseKey(hkeyComponents);
1049 UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
1052 WCHAR szwProduct[GUID_SIZE];
1053 LPWSTR szwComponent = NULL;
1055 TRACE("%s %d %p\n", debugstr_a(szComponent), index, szProduct);
1059 szwComponent = strdupAtoW( szComponent );
1061 return ERROR_OUTOFMEMORY;
1064 r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
1065 if( r == ERROR_SUCCESS )
1067 WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
1068 szProduct, GUID_SIZE, NULL, NULL);
1071 msi_free( szwComponent);
1076 UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
1080 WCHAR szValName[SQUISH_GUID_SIZE];
1082 TRACE("%s %d %p\n", debugstr_w(szComponent), index, szProduct);
1084 r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE);
1085 if( r != ERROR_SUCCESS )
1086 return ERROR_NO_MORE_ITEMS;
1088 sz = SQUISH_GUID_SIZE;
1089 r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
1090 if( r == ERROR_SUCCESS )
1091 unsquash_guid(szValName, szProduct);
1093 RegCloseKey(hkeyComp);
1098 static UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
1099 awstring *lpQualBuf, DWORD* pcchQual,
1100 awstring *lpAppBuf, DWORD* pcchAppBuf )
1102 DWORD name_sz, val_sz, name_max, val_max, type, ofs;
1103 LPWSTR name = NULL, val = NULL;
1107 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1108 lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
1111 return ERROR_INVALID_PARAMETER;
1113 r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
1114 if (r != ERROR_SUCCESS)
1115 return ERROR_UNKNOWN_COMPONENT;
1117 /* figure out how big the name is we want to return */
1119 r = ERROR_OUTOFMEMORY;
1120 name = msi_alloc( name_max * sizeof(WCHAR) );
1125 r = ERROR_OUTOFMEMORY;
1126 val = msi_alloc( val_max );
1130 /* loop until we allocate enough memory */
1135 r = RegEnumValueW( key, iIndex, name, &name_sz,
1136 NULL, &type, (LPBYTE)val, &val_sz );
1137 if (r == ERROR_SUCCESS)
1139 if (r != ERROR_MORE_DATA)
1142 if (type != REG_MULTI_SZ)
1144 ERR("component data has wrong type (%d)\n", type);
1148 r = ERROR_OUTOFMEMORY;
1149 if ((name_sz+1) >= name_max)
1153 name = msi_alloc( name_max * sizeof (WCHAR) );
1158 if (val_sz > val_max)
1160 val_max = val_sz + sizeof (WCHAR);
1162 val = msi_alloc( val_max * sizeof (WCHAR) );
1167 ERR("should be enough data, but isn't %d %d\n", name_sz, val_sz );
1172 r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
1173 if (r != ERROR_SUCCESS)
1176 TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
1178 r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
1179 r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
1181 if (r2 != ERROR_SUCCESS)
1192 /*************************************************************************
1193 * MsiEnumComponentQualifiersA [MSI.@]
1195 UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
1196 LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
1197 LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
1199 awstring qual, appdata;
1203 TRACE("%s %08x %p %p %p %p\n", debugstr_a(szComponent), iIndex,
1204 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1205 pcchApplicationDataBuf);
1207 comp = strdupAtoW( szComponent );
1208 if (szComponent && !comp)
1209 return ERROR_OUTOFMEMORY;
1211 qual.unicode = FALSE;
1212 qual.str.a = lpQualifierBuf;
1214 appdata.unicode = FALSE;
1215 appdata.str.a = lpApplicationDataBuf;
1217 r = MSI_EnumComponentQualifiers( comp, iIndex,
1218 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1223 /*************************************************************************
1224 * MsiEnumComponentQualifiersW [MSI.@]
1226 UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
1227 LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
1228 LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
1230 awstring qual, appdata;
1232 TRACE("%s %08x %p %p %p %p\n", debugstr_w(szComponent), iIndex,
1233 lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
1234 pcchApplicationDataBuf);
1236 qual.unicode = TRUE;
1237 qual.str.w = lpQualifierBuf;
1239 appdata.unicode = TRUE;
1240 appdata.str.w = lpApplicationDataBuf;
1242 return MSI_EnumComponentQualifiers( szComponent, iIndex,
1243 &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
1246 /*************************************************************************
1247 * MsiEnumRelatedProductsW [MSI.@]
1250 UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
1251 DWORD iProductIndex, LPWSTR lpProductBuf)
1255 DWORD dwSize = SQUISH_GUID_SIZE;
1256 WCHAR szKeyName[SQUISH_GUID_SIZE];
1258 TRACE("%s %u %u %p\n", debugstr_w(szUpgradeCode), dwReserved,
1259 iProductIndex, lpProductBuf);
1261 if (NULL == szUpgradeCode)
1262 return ERROR_INVALID_PARAMETER;
1263 if (NULL == lpProductBuf)
1264 return ERROR_INVALID_PARAMETER;
1266 r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
1267 if (r != ERROR_SUCCESS)
1268 return ERROR_NO_MORE_ITEMS;
1270 r = RegEnumValueW(hkey, iProductIndex, szKeyName, &dwSize, NULL, NULL, NULL, NULL);
1271 if( r == ERROR_SUCCESS )
1272 unsquash_guid(szKeyName, lpProductBuf);
1278 /*************************************************************************
1279 * MsiEnumRelatedProductsA [MSI.@]
1282 UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
1283 DWORD iProductIndex, LPSTR lpProductBuf)
1285 LPWSTR szwUpgradeCode = NULL;
1286 WCHAR productW[GUID_SIZE];
1289 TRACE("%s %u %u %p\n", debugstr_a(szUpgradeCode), dwReserved,
1290 iProductIndex, lpProductBuf);
1294 szwUpgradeCode = strdupAtoW( szUpgradeCode );
1295 if( !szwUpgradeCode )
1296 return ERROR_OUTOFMEMORY;
1299 r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
1300 iProductIndex, productW );
1301 if (r == ERROR_SUCCESS)
1303 WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
1304 lpProductBuf, GUID_SIZE, NULL, NULL );
1306 msi_free( szwUpgradeCode);
1310 /***********************************************************************
1311 * MsiEnumPatchesA [MSI.@]
1313 UINT WINAPI MsiEnumPatchesA( LPCSTR szProduct, DWORD iPatchIndex,
1314 LPSTR lpPatchBuf, LPSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1316 FIXME("%s %d %p %p %p\n", debugstr_a(szProduct),
1317 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1318 return ERROR_NO_MORE_ITEMS;
1321 /***********************************************************************
1322 * MsiEnumPatchesW [MSI.@]
1324 UINT WINAPI MsiEnumPatchesW( LPCWSTR szProduct, DWORD iPatchIndex,
1325 LPWSTR lpPatchBuf, LPWSTR lpTransformsBuf, DWORD* pcchTransformsBuf)
1327 FIXME("%s %d %p %p %p\n", debugstr_w(szProduct),
1328 iPatchIndex, lpPatchBuf, lpTransformsBuf, pcchTransformsBuf);
1329 return ERROR_NO_MORE_ITEMS;
1332 UINT WINAPI MsiEnumProductsExA( LPCSTR szProductCode, LPCSTR szUserSid,
1333 DWORD dwContext, DWORD dwIndex, LPSTR szInstalledProductCode,
1334 MSIINSTALLCONTEXT* pdwInstalledContext, LPSTR szSid, LPDWORD pcchSid)
1336 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_a(szProductCode), debugstr_a(szUserSid),
1337 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1339 return ERROR_NO_MORE_ITEMS;
1342 UINT WINAPI MsiEnumProductsExW( LPCWSTR szProductCode, LPCWSTR szUserSid,
1343 DWORD dwContext, DWORD dwIndex, LPWSTR szInstalledProductCode,
1344 MSIINSTALLCONTEXT* pdwInstalledContext, LPWSTR szSid, LPDWORD pcchSid)
1346 FIXME("%s %s %d %d %p %p %p %p\n", debugstr_w(szProductCode), debugstr_w(szUserSid),
1347 dwContext, dwIndex, szInstalledProductCode, pdwInstalledContext,
1349 return ERROR_NO_MORE_ITEMS;