'C','o','m','p','o','n','e','n','t','s','\\',
'%','s',0};
+static const WCHAR szUser_Components_fmt[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'C','o','m','p','o','n','e','n','t','s','\\',
+'%','s',0};
+
static const WCHAR szUninstall_fmt[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'P','r','o','d','u','c','t','s','\\',
'%','s',0};
+static const WCHAR szInstaller_UpgradeCodes[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'W','i','n','d','o','w','s','\\',
+'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'U','p','g','r','a','d','e','C','o','d','e','s',0};
+
+static const WCHAR szInstaller_UpgradeCodes_fmt[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'W','i','n','d','o','w','s','\\',
+'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'U','p','g','r','a','d','e','C','o','d','e','s','\\',
+'%','s',0};
+
+static const WCHAR szInstaller_UserUpgradeCodes[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'U','p','g','r','a','d','e','C','o','d','e','s',0};
+
+static const WCHAR szInstaller_UserUpgradeCodes_fmt[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'U','p','g','r','a','d','e','C','o','d','e','s','\\',
+'%','s',0};
+
+
+#define SQUISH_GUID_SIZE 33
+
BOOL unsquash_guid(LPCWSTR in, LPWSTR out)
{
DWORD i,n=0;
{
DWORD i, val = 0, base = 1, *p;
+ if (!str)
+ return FALSE;
+
p = (DWORD*) guid;
for( i=0; i<20; i++ )
{
return rc;
}
+UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create)
+{
+ UINT rc;
+ WCHAR squished_cc[GUID_SIZE];
+ WCHAR keypath[0x200];
+
+ TRACE("%s\n",debugstr_w(szComponent));
+ squash_guid(szComponent,squished_cc);
+ TRACE("squished (%s)\n", debugstr_w(squished_cc));
+
+ sprintfW(keypath,szUser_Components_fmt,squished_cc);
+
+ if (create)
+ rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
+ else
+ rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
+
+ return rc;
+}
+
UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create)
{
UINT rc;
return rc;
}
+UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
+{
+ UINT rc;
+ WCHAR squished_pc[GUID_SIZE];
+ WCHAR keypath[0x200];
+
+ TRACE("%s\n",debugstr_w(szUpgradeCode));
+ squash_guid(szUpgradeCode,squished_pc);
+ TRACE("squished (%s)\n", debugstr_w(squished_pc));
+
+ sprintfW(keypath,szInstaller_UpgradeCodes_fmt,squished_pc);
+
+ if (create)
+ rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,keypath,key);
+ else
+ rc = RegOpenKeyW(HKEY_LOCAL_MACHINE,keypath,key);
+
+ return rc;
+}
+
+UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create)
+{
+ UINT rc;
+ WCHAR squished_pc[GUID_SIZE];
+ WCHAR keypath[0x200];
+
+ TRACE("%s\n",debugstr_w(szUpgradeCode));
+ squash_guid(szUpgradeCode,squished_pc);
+ TRACE("squished (%s)\n", debugstr_w(squished_pc));
+
+ sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc);
+
+ if (create)
+ rc = RegCreateKeyW(HKEY_CURRENT_USER,keypath,key);
+ else
+ rc = RegOpenKeyW(HKEY_CURRENT_USER,keypath,key);
+
+ return rc;
+}
+
+
/*************************************************************************
* MsiDecomposeDescriptorW [MSI.@]
*
*
* PARAMS
* szDescriptor [I] the descriptor to decompose
- * szProduct [O] buffer of MAX_FEATURE_CHARS for the product guid
- * szFeature [O] buffer of MAX_FEATURE_CHARS for the feature code
- * szComponent [O] buffer of MAX_FEATURE_CHARS for the component guid
+ * szProduct [O] buffer of MAX_FEATURE_CHARS+1 for the product guid
+ * szFeature [O] buffer of MAX_FEATURE_CHARS+1 for the feature code
+ * szComponent [O] buffer of MAX_FEATURE_CHARS+1 for the component guid
* pUsed [O] the length of the descriptor
*
* RETURNS
len = (p - &szDescriptor[20]);
if( len > MAX_FEATURE_CHARS )
return ERROR_INVALID_PARAMETER;
- memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
- szFeature[len] = 0;
+ if (szFeature)
+ {
+ memcpy( szFeature, &szDescriptor[20], len*sizeof(WCHAR) );
+ szFeature[len] = 0;
+ }
- TRACE("feature %s\n", debugstr_w( szFeature ));
+ TRACE("feature %s\n", debugstr_w( &szDescriptor[20] ));
r = decode_base85_guid( p+1, &component );
if( !r )
TRACE("component %s\n", debugstr_guid( &component ));
- StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
- StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
+ if (szProduct)
+ StringFromGUID2( &product, szProduct, MAX_FEATURE_CHARS+1 );
+ if (szComponent)
+ StringFromGUID2( &component, szComponent, MAX_FEATURE_CHARS+1 );
len = ( &p[21] - szDescriptor );
TRACE("length = %d\n", len);
WCHAR product[MAX_FEATURE_CHARS+1];
WCHAR feature[MAX_FEATURE_CHARS+1];
WCHAR component[MAX_FEATURE_CHARS+1];
- LPWSTR str = NULL;
- UINT r, len;
+ LPWSTR str = NULL, p = NULL, f = NULL, c = NULL;
+ UINT r;
TRACE("%s %p %p %p %p\n", debugstr_a(szDescriptor), szProduct,
szFeature, szComponent, pUsed);
- if( szDescriptor )
- {
- len = MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, NULL, 0 );
- str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
- MultiByteToWideChar( CP_ACP, 0, szDescriptor, -1, str, len );
- }
+ str = strdupAtoW( szDescriptor );
+ if( szDescriptor && !str )
+ return ERROR_OUTOFMEMORY;
+
+ if (szProduct)
+ p = product;
+ if (szFeature)
+ f = feature;
+ if (szComponent)
+ c = component;
- r = MsiDecomposeDescriptorW( str, product, feature, component, pUsed );
+ r = MsiDecomposeDescriptorW( str, p, f, c, pUsed );
- WideCharToMultiByte( CP_ACP, 0, product, MAX_FEATURE_CHARS+1,
+ WideCharToMultiByte( CP_ACP, 0, p, MAX_FEATURE_CHARS+1,
szProduct, MAX_FEATURE_CHARS+1, NULL, NULL );
- WideCharToMultiByte( CP_ACP, 0, feature, MAX_FEATURE_CHARS+1,
+ WideCharToMultiByte( CP_ACP, 0, f, MAX_FEATURE_CHARS+1,
szFeature, MAX_FEATURE_CHARS+1, NULL, NULL );
- WideCharToMultiByte( CP_ACP, 0, component, MAX_FEATURE_CHARS+1,
+ WideCharToMultiByte( CP_ACP, 0, c, MAX_FEATURE_CHARS+1,
szComponent, MAX_FEATURE_CHARS+1, NULL, NULL );
- HeapFree( GetProcessHeap(), 0, str );
+ msi_free( str );
+
+ return r;
+}
+
+UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
+{
+ DWORD r;
+ WCHAR szwGuid[GUID_SIZE];
+
+ TRACE("%ld %p\n",index,lpguid);
+
+ if (NULL == lpguid)
+ return ERROR_INVALID_PARAMETER;
+ r = MsiEnumProductsW(index, szwGuid);
+ if( r == ERROR_SUCCESS )
+ WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
+{
+ HKEY hkeyFeatures = 0;
+ DWORD r;
+ WCHAR szKeyName[SQUISH_GUID_SIZE];
+
+ TRACE("%ld %p\n",index,lpguid);
+
+ if (NULL == lpguid)
+ return ERROR_INVALID_PARAMETER;
+
+ r = MSIREG_OpenFeatures(&hkeyFeatures);
+ if( r != ERROR_SUCCESS )
+ return ERROR_NO_MORE_ITEMS;
+
+ r = RegEnumKeyW(hkeyFeatures, index, szKeyName, SQUISH_GUID_SIZE);
+ if( r == ERROR_SUCCESS )
+ unsquash_guid(szKeyName, lpguid);
+ RegCloseKey(hkeyFeatures);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index,
+ LPSTR szFeature, LPSTR szParent)
+{
+ DWORD r;
+ WCHAR szwFeature[GUID_SIZE], szwParent[GUID_SIZE];
+ LPWSTR szwProduct = NULL;
+
+ TRACE("%s %ld %p %p\n",debugstr_a(szProduct),index,szFeature,szParent);
+
+ if( szProduct )
+ {
+ szwProduct = strdupAtoW( szProduct );
+ if( !szwProduct )
+ return ERROR_OUTOFMEMORY;
+ }
+
+ r = MsiEnumFeaturesW(szwProduct, index, szwFeature, szwParent);
+ if( r == ERROR_SUCCESS )
+ {
+ WideCharToMultiByte(CP_ACP, 0, szwFeature, -1,
+ szFeature, GUID_SIZE, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, szwParent, -1,
+ szParent, GUID_SIZE, NULL, NULL);
+ }
+ msi_free( szwProduct);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumFeaturesW(LPCWSTR szProduct, DWORD index,
+ LPWSTR szFeature, LPWSTR szParent)
+{
+ HKEY hkeyProduct = 0;
+ DWORD r, sz;
+
+ TRACE("%s %ld %p %p\n",debugstr_w(szProduct),index,szFeature,szParent);
+
+ r = MSIREG_OpenFeaturesKey(szProduct,&hkeyProduct,FALSE);
+ if( r != ERROR_SUCCESS )
+ return ERROR_NO_MORE_ITEMS;
+
+ sz = GUID_SIZE;
+ r = RegEnumValueW(hkeyProduct, index, szFeature, &sz, NULL, NULL, NULL, NULL);
+ RegCloseKey(hkeyProduct);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumComponentsA(DWORD index, LPSTR lpguid)
+{
+ DWORD r;
+ WCHAR szwGuid[GUID_SIZE];
+
+ TRACE("%ld %p\n",index,lpguid);
+
+ r = MsiEnumComponentsW(index, szwGuid);
+ if( r == ERROR_SUCCESS )
+ WideCharToMultiByte(CP_ACP, 0, szwGuid, -1, lpguid, GUID_SIZE, NULL, NULL);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumComponentsW(DWORD index, LPWSTR lpguid)
+{
+ HKEY hkeyComponents = 0;
+ DWORD r;
+ WCHAR szKeyName[SQUISH_GUID_SIZE];
+
+ TRACE("%ld %p\n",index,lpguid);
+
+ r = MSIREG_OpenComponents(&hkeyComponents);
+ if( r != ERROR_SUCCESS )
+ return ERROR_NO_MORE_ITEMS;
+
+ r = RegEnumKeyW(hkeyComponents, index, szKeyName, SQUISH_GUID_SIZE);
+ if( r == ERROR_SUCCESS )
+ unsquash_guid(szKeyName, lpguid);
+ RegCloseKey(hkeyComponents);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumClientsA(LPCSTR szComponent, DWORD index, LPSTR szProduct)
+{
+ DWORD r;
+ WCHAR szwProduct[GUID_SIZE];
+ LPWSTR szwComponent = NULL;
+
+ TRACE("%s %ld %p\n",debugstr_a(szComponent),index,szProduct);
+
+ if( szComponent )
+ {
+ szwComponent = strdupAtoW( szComponent );
+ if( !szwComponent )
+ return ERROR_OUTOFMEMORY;
+ }
+
+ r = MsiEnumClientsW(szComponent?szwComponent:NULL, index, szwProduct);
+ if( r == ERROR_SUCCESS )
+ {
+ WideCharToMultiByte(CP_ACP, 0, szwProduct, -1,
+ szProduct, GUID_SIZE, NULL, NULL);
+ }
+
+ msi_free( szwComponent);
+
+ return r;
+}
+
+UINT WINAPI MsiEnumClientsW(LPCWSTR szComponent, DWORD index, LPWSTR szProduct)
+{
+ HKEY hkeyComp = 0;
+ DWORD r, sz;
+ WCHAR szValName[SQUISH_GUID_SIZE];
+
+ TRACE("%s %ld %p\n",debugstr_w(szComponent),index,szProduct);
+
+ r = MSIREG_OpenComponentsKey(szComponent,&hkeyComp,FALSE);
+ if( r != ERROR_SUCCESS )
+ return ERROR_NO_MORE_ITEMS;
+
+ sz = SQUISH_GUID_SIZE;
+ r = RegEnumValueW(hkeyComp, index, szValName, &sz, NULL, NULL, NULL, NULL);
+ if( r == ERROR_SUCCESS )
+ unsquash_guid(szValName, szProduct);
+
+ RegCloseKey(hkeyComp);
+
+ return r;
+}
+
+UINT WINAPI MSI_EnumComponentQualifiers( LPCWSTR szComponent, DWORD iIndex,
+ awstring *lpQualBuf, DWORD* pcchQual,
+ awstring *lpAppBuf, DWORD* pcchAppBuf )
+{
+ DWORD name_sz, val_sz, name_max, val_max, type, ofs;
+ LPWSTR name = NULL, val = NULL;
+ UINT r, r2;
+ HKEY key;
+
+ TRACE("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex,
+ lpQualBuf, pcchQual, lpAppBuf, pcchAppBuf);
+
+ if (!szComponent)
+ return ERROR_INVALID_PARAMETER;
+
+ r = MSIREG_OpenUserComponentsKey( szComponent, &key, FALSE );
+ if (r != ERROR_SUCCESS)
+ return ERROR_UNKNOWN_COMPONENT;
+
+ /* figure out how big the name is we want to return */
+ name_max = 0x10;
+ r = ERROR_OUTOFMEMORY;
+ name = msi_alloc( name_max * sizeof(WCHAR) );
+ if (!name)
+ goto end;
+
+ val_max = 0x10;
+ r = ERROR_OUTOFMEMORY;
+ val = msi_alloc( val_max );
+ if (!val)
+ goto end;
+
+ /* loop until we allocate enough memory */
+ while (1)
+ {
+ name_sz = name_max;
+ val_sz = val_max;
+ r = RegEnumValueW( key, iIndex, name, &name_sz,
+ NULL, &type, (LPBYTE)val, &val_sz );
+ if (r == ERROR_SUCCESS)
+ break;
+ if (r != ERROR_MORE_DATA)
+ goto end;
+
+ if (type != REG_MULTI_SZ)
+ {
+ ERR("component data has wrong type (%ld)\n", type);
+ goto end;
+ }
+
+ r = ERROR_OUTOFMEMORY;
+ if ((name_sz+1) >= name_max)
+ {
+ name_max *= 2;
+ msi_free( name );
+ name = msi_alloc( name_max * sizeof (WCHAR) );
+ if (!name)
+ goto end;
+ continue;
+ }
+ if (val_sz > val_max)
+ {
+ val_max = val_sz + sizeof (WCHAR);
+ val = msi_alloc( val_max * sizeof (WCHAR) );
+ if (!val)
+ goto end;
+ continue;
+ }
+ ERR("should be enough data, but isn't %ld %ld\n", name_sz, val_sz );
+ goto end;
+ }
+
+ ofs = 0;
+ r = MsiDecomposeDescriptorW( val, NULL, NULL, NULL, &ofs );
+ if (r != ERROR_SUCCESS)
+ goto end;
+
+ TRACE("Providing %s and %s\n", debugstr_w(name), debugstr_w(val+ofs));
+
+ r = msi_strcpy_to_awstring( name, lpQualBuf, pcchQual );
+ r2 = msi_strcpy_to_awstring( val+ofs, lpAppBuf, pcchAppBuf );
+
+ if (r2 != ERROR_SUCCESS)
+ r = r2;
+
+end:
+ msi_free(val);
+ msi_free(name);
+ RegCloseKey(key);
+
+ return r;
+}
+
+/*************************************************************************
+ * MsiEnumComponentQualifiersA [MSI.@]
+ */
+UINT WINAPI MsiEnumComponentQualifiersA( LPCSTR szComponent, DWORD iIndex,
+ LPSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
+ LPSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
+{
+ awstring qual, appdata;
+ LPWSTR comp;
+ UINT r;
+
+ TRACE("%s %08lx %p %p %p %p\n", debugstr_a(szComponent), iIndex,
+ lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
+ pcchApplicationDataBuf);
+
+ comp = strdupAtoW( szComponent );
+ if (szComponent && !comp)
+ return ERROR_OUTOFMEMORY;
+
+ qual.unicode = FALSE;
+ qual.str.a = lpQualifierBuf;
+
+ appdata.unicode = FALSE;
+ appdata.str.a = lpApplicationDataBuf;
+
+ r = MSI_EnumComponentQualifiers( comp, iIndex,
+ &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
+ msi_free( comp );
+ return r;
+}
+
+/*************************************************************************
+ * MsiEnumComponentQualifiersW [MSI.@]
+ */
+UINT WINAPI MsiEnumComponentQualifiersW( LPCWSTR szComponent, DWORD iIndex,
+ LPWSTR lpQualifierBuf, DWORD* pcchQualifierBuf,
+ LPWSTR lpApplicationDataBuf, DWORD* pcchApplicationDataBuf )
+{
+ awstring qual, appdata;
+
+ TRACE("%s %08lx %p %p %p %p\n", debugstr_w(szComponent), iIndex,
+ lpQualifierBuf, pcchQualifierBuf, lpApplicationDataBuf,
+ pcchApplicationDataBuf);
+
+ qual.unicode = TRUE;
+ qual.str.w = lpQualifierBuf;
+
+ appdata.unicode = TRUE;
+ appdata.str.w = lpApplicationDataBuf;
+
+ return MSI_EnumComponentQualifiers( szComponent, iIndex,
+ &qual, pcchQualifierBuf, &appdata, pcchApplicationDataBuf );
+}
+
+/*************************************************************************
+ * MsiEnumRelatedProductsW [MSI.@]
+ *
+ */
+UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved,
+ DWORD iProductIndex, LPWSTR lpProductBuf)
+{
+ UINT r;
+ HKEY hkey;
+ WCHAR szKeyName[SQUISH_GUID_SIZE];
+
+ TRACE("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved,
+ iProductIndex, lpProductBuf);
+
+ if (NULL == szUpgradeCode)
+ return ERROR_INVALID_PARAMETER;
+ if (NULL == lpProductBuf)
+ return ERROR_INVALID_PARAMETER;
+
+ r = MSIREG_OpenUpgradeCodesKey(szUpgradeCode, &hkey, FALSE);
+ if (r != ERROR_SUCCESS)
+ return ERROR_NO_MORE_ITEMS;
+
+ r = RegEnumKeyW(hkey, iProductIndex, szKeyName, SQUISH_GUID_SIZE);
+ if( r == ERROR_SUCCESS )
+ unsquash_guid(szKeyName, lpProductBuf);
+ RegCloseKey(hkey);
+
+ return r;
+}
+
+/*************************************************************************
+ * MsiEnumRelatedProductsA [MSI.@]
+ *
+ */
+UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved,
+ DWORD iProductIndex, LPSTR lpProductBuf)
+{
+ LPWSTR szwUpgradeCode = NULL;
+ WCHAR productW[GUID_SIZE];
+ UINT r;
+
+ TRACE("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved,
+ iProductIndex, lpProductBuf);
+
+ if (szUpgradeCode)
+ {
+ szwUpgradeCode = strdupAtoW( szUpgradeCode );
+ if( !szwUpgradeCode )
+ return ERROR_OUTOFMEMORY;
+ }
+
+ r = MsiEnumRelatedProductsW( szwUpgradeCode, dwReserved,
+ iProductIndex, productW );
+ if (r == ERROR_SUCCESS)
+ {
+ WideCharToMultiByte( CP_ACP, 0, productW, GUID_SIZE,
+ lpProductBuf, GUID_SIZE, NULL, NULL );
+ }
+ msi_free( szwUpgradeCode);
return r;
}