msi: action.c new actions and fixes

Aric Stewart aric at codeweavers.com
Sat Jan 15 04:07:58 CST 2005


implementations for SelfRegModules and PublishFeatures
set default ACTION property for Install
Deformat more than JUST properties properly. Allows for Files and 		 
Component paths in deformat.
Properly deformat a LaunchCondition failure dialog box.
Resolve and save Registry Keypaths
Write the Features published keys more correctly. still some problems.
-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.68
diff -u -u -r1.68 action.c
--- dlls/msi/action.c	14 Jan 2005 16:50:39 -0000	1.68
+++ dlls/msi/action.c	15 Jan 2005 10:07:51 -0000
@@ -160,6 +160,8 @@
 static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
 static UINT ACTION_PublishProduct(MSIPACKAGE *package);
 static UINT ACTION_WriteIniValues(MSIPACKAGE *package);
+static UINT ACTION_SelfRegModules(MSIPACKAGE *package);
+static UINT ACTION_PublishFeatures(MSIPACKAGE *package);
 
 static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, 
                                 const LPWSTR target, const INT type);
@@ -175,7 +177,8 @@
 static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data);
 static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name,
                            BOOL source, BOOL set_prop, MSIFOLDER **folder);
-
+static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, 
+                            LPWSTR *FilePath);
 static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
  
 /*
@@ -226,6 +229,10 @@
 {'P','u','b','l','i','s','h','P','r','o','d','u','c','t',0};
 const static WCHAR szWriteIniValues[] = 
 {'W','r','i','t','e','I','n','i','V','a','l','u','e','s',0};
+const static WCHAR szSelfRegModules[] = 
+{'S','e','l','f','R','e','g','M','o','d','u','l','e','s',0};
+const static WCHAR szPublishFeatures[] = 
+{'P','u','b','l','i','s','h','F','e','a','t','u','r','e','s',0};
 
 /******************************************************** 
  * helper functions to get around current HACKS and such
@@ -767,6 +774,10 @@
     WCHAR buffer[10];
     UINT rc;
     static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
+    static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
+    static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
+
+    MSI_SetPropertyW(package, szAction, szInstall);
 
     if (szPackagePath)   
     {
@@ -1225,6 +1236,10 @@
         rc = ACTION_PublishProduct(package);
     else if (strcmpW(action,szWriteIniValues)==0)
         rc = ACTION_WriteIniValues(package);
+    else if (strcmpW(action,szSelfRegModules)==0)
+        rc = ACTION_SelfRegModules(package);
+    else if (strcmpW(action,szPublishFeatures)==0)
+        rc = ACTION_PublishFeatures(package);
 
     /*
      Called during iTunes but unimplemented and seem important
@@ -1411,6 +1426,8 @@
 }
 
 typedef UINT __stdcall CustomEntry(MSIHANDLE);
+typedef UINT __stdcall DllRegisterServer();
+
 typedef struct 
 {
         MSIPACKAGE *package;
@@ -2684,7 +2701,7 @@
                     WCHAR filever[0x100];
                     VS_FIXEDFILEINFO *lpVer;
 
-                    FIXME("Version comparison.. \n");
+                    TRACE("Version comparison.. \n");
                     versize = GetFileVersionInfoSizeW(file->TargetPath,&handle);
                     version = HeapAlloc(GetProcessHeap(),0,versize);
                     GetFileVersionInfoW(file->TargetPath, 0, versize, version);
@@ -3694,9 +3711,10 @@
     DWORD size=0;
     DWORD chunk=0;
     WCHAR key[0x100];
-    LPWSTR value;
+    LPWSTR value = NULL;
     DWORD sz;
     UINT rc;
+    INT index;
 
     if (ptr==NULL)
     {
@@ -3741,15 +3759,60 @@
     mark++;
     TRACE("Current %s .. %s\n",debugstr_w(*data),debugstr_w(mark));
     sz = 0;
-    rc = MSI_GetPropertyW(package, key, NULL, &sz);
-    if ((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA))
+    /* expand what we can deformat... Again, this should become a bison file */
+    switch (key[0])
+    {
+        case '~':
+            ERR("UNHANDLED DEFORMAT.. [~] should be NULL\n");
+            rc = ERROR_FUNCTION_FAILED;
+            break;
+        case '$':
+            ERR("POORLY HANDLED DEFORMAT.. [$componentkey] \n");
+            index = get_loaded_component(package,&key[1]);
+            if (index >= 0)
+            {
+                value = resolve_folder(package, 
+                                       package->components[index].Directory, 
+                                       FALSE, FALSE, NULL);
+                rc = 0;
+            }
+            else
+                rc = ERROR_FUNCTION_FAILED;
+            break;
+        case '#':
+            index = get_loaded_file(package,&key[1]);
+            if (index >=0)
+            {
+                sz = strlenW(package->files[index].TargetPath);
+                value = dupstrW(package->files[index].TargetPath);
+                rc= ERROR_SUCCESS;
+            }
+            else
+                rc = ERROR_FUNCTION_FAILED;
+            break;
+        case '\\':
+            value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2);
+            value[0] =  key[1];
+            rc = ERROR_SUCCESS;
+            break;
+        case '%':
+            sz  = GetEnvironmentVariableW(&key[1],NULL,0);
+            sz++;
+            value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
+            GetEnvironmentVariableW(&key[1],value,sz);
+            rc = ERROR_SUCCESS;
+            break;
+        default:
+            rc = MSI_GetPropertyW(package, key, NULL, &sz);
+            sz++;
+            value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
+            MSI_GetPropertyW(package, key, value, &sz);
+            break;
+    }
+    if (((rc == ERROR_SUCCESS) || (rc == ERROR_MORE_DATA))&& value!=NULL)
     {
         LPWSTR newdata;
 
-        sz++;
-        value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
-        MSI_GetPropertyW(package, key, value, &sz);
-
         chunk = (strlenW(value)+1) * sizeof(WCHAR);
         size+=chunk;   
         newdata = HeapReAlloc(GetProcessHeap(),0,*data,size);
@@ -3875,9 +3938,12 @@
 
         if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE)
         {
+            LPWSTR deformated;
             message = load_dynamic_stringW(row,2);
-            MessageBoxW(NULL,message,title,MB_OK);
+            deformat_string(package,message,&deformated); 
+            MessageBoxW(NULL,deformated,title,MB_OK);
             HeapFree(GetProcessHeap(),0,message);
+            HeapFree(GetProcessHeap(),0,deformated);
             rc = ERROR_FUNCTION_FAILED;
         }
         HeapFree(GetProcessHeap(),0,cond);
@@ -3898,9 +3964,71 @@
         LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL);
         return p;
     }
-    if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20))
+    if (cmp->Attributes & 0x4)
     {
-        FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n");
+        MSIQUERY * view;
+        MSIRECORD * row = 0;
+        UINT rc,root,len;
+        LPWSTR key,deformated,buffer,name,deformated_name;
+        static const WCHAR ExecSeqQuery[] = {
+        's','e','l','e','c','t',' ','*',' ',
+        'f','r','o','m',' ','R','e','g','i','s','t','r','y',' ',
+'w','h','e','r','e',' ','R','e','g','i','s','t','r','y',' ','=',' '
+,'`','%','s','`',0 };
+        static const WCHAR fmt[]={'%','0','2','i',':','%','s',0};
+        static const WCHAR fmt2[]={'%','0','2','i',':','%','s','\\','%','s',0};
+
+        rc = ACTION_OpenQuery(package->db,&view,ExecSeqQuery,cmp->KeyPath);
+
+        if (rc!=ERROR_SUCCESS)
+            return NULL;
+
+        rc = MSI_ViewExecute(view, 0);
+        if (rc != ERROR_SUCCESS)
+        {
+            MSI_ViewClose(view);
+            msiobj_release(&view->hdr);
+            return NULL;
+        }
+
+        rc = MSI_ViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+        {
+            MSI_ViewClose(view);
+            msiobj_release(&view->hdr);
+            return NULL;
+        }
+
+        root = MSI_RecordGetInteger(row,2);
+        key = load_dynamic_stringW(row, 3);
+        name = load_dynamic_stringW(row, 4);
+        deformat_string(package, key , &deformated);
+        deformat_string(package, name, &deformated_name);
+
+        len = strlenW(deformated) + 5;
+        if (deformated_name)
+            len+=strlenW(deformated_name);
+
+        buffer = HeapAlloc(GetProcessHeap(),0, len *sizeof(WCHAR));
+
+        if (deformated_name)
+            sprintfW(buffer,fmt2,root,deformated,deformated_name);
+        else
+            sprintfW(buffer,fmt,root,deformated);
+
+        HeapFree(GetProcessHeap(),0,key);
+        HeapFree(GetProcessHeap(),0,deformated);
+        HeapFree(GetProcessHeap(),0,name);
+        HeapFree(GetProcessHeap(),0,deformated_name);
+        msiobj_release(&row->hdr);
+        MSI_ViewClose(view);
+        msiobj_release(&view->hdr);
+
+        return buffer;
+    }
+    else if (cmp->Attributes & 0x20)
+    {
+        FIXME("UNIMPLEMENTED keypath as ODBC Source\n");
         return NULL;
     }
     else
@@ -3940,8 +4068,6 @@
          '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',0 };
-    static const WCHAR szFeatures[] = {
-         'F','e','a','t','u','r','e','s',0 };
     static const WCHAR szComponents[] = {
          'C','o','m','p','o','n','e','n','t','s',0 };
 
@@ -3958,48 +4084,6 @@
     if (rc != ERROR_SUCCESS)
         goto end;
 
-    rc = RegCreateKeyW(hkey,szFeatures,&hkey2);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
-    if (rc != ERROR_SUCCESS)
-        goto end;
-
-    /* here the guids are base 85 encoded */
-    for (i = 0; i < package->loaded_features; i++)
-    {
-        LPWSTR data = NULL;
-        GUID clsid;
-        int j;
-        INT size;
-
-        size = package->features[i].ComponentCount*21*sizeof(WCHAR);
-        data = HeapAlloc(GetProcessHeap(), 0, size);
-
-        data[0] = 0;
-        for (j = 0; j < package->features[i].ComponentCount; j++)
-        {
-            WCHAR buf[21];
-            TRACE("From %s\n",debugstr_w(package->components
-                            [package->features[i].Components[j]].ComponentId));
-            CLSIDFromString(package->components
-                            [package->features[i].Components[j]].ComponentId,
-                            &clsid);
-            encode_base85_guid(&clsid,buf);
-            TRACE("to %s\n",debugstr_w(buf));
-            strcatW(data,buf);
-        }
-
-        size = strlenW(data)*sizeof(WCHAR);
-        RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ,
-                       (LPSTR)data,size);
-        HeapFree(GetProcessHeap(),0,data);
-    }
-
-    RegCloseKey(hkey3);
-    RegCloseKey(hkey2);
-
     rc = RegCreateKeyW(hkey,szComponents,&hkey2);
     if (rc != ERROR_SUCCESS)
         goto end;
@@ -4418,9 +4502,12 @@
     return rc;
 }
 
-static UINT register_progid_base(MSIRECORD * row, LPWSTR clsid)
+static UINT register_progid_base(MSIPACKAGE* package, MSIRECORD * row, 
+                                LPWSTR clsid)
 {
     static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
+    static const WCHAR szDefaultIcon[] = {
+        'D','e','f','a','u','l','t','I','c','o','n',0};
     HKEY hkey,hkey2;
     WCHAR buffer[0x100];
     DWORD sz;
@@ -4458,7 +4545,25 @@
         return ERROR_FUNCTION_FAILED;
     }
     if (!MSI_RecordIsNull(row,5))
-        FIXME ("UNHANDLED icon in Progid\n");
+    {
+        INT index = MSI_RecordGetInteger(row,6); 
+        LPWSTR FileName = load_dynamic_stringW(row,5);
+        LPWSTR FilePath,IconPath;
+        static const WCHAR fmt[] = {'%','s',',','%','i',0};
+
+        RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
+        build_icon_path(package,FileName,&FilePath);
+       
+        IconPath = HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
+                    sizeof(WCHAR));
+
+        sprintfW(IconPath,fmt,FilePath,index);
+        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)IconPath,
+                           (strlenW(IconPath)+1) * sizeof(WCHAR));
+        HeapFree(GetProcessHeap(),0,FilePath);
+        HeapFree(GetProcessHeap(),0,FileName);
+        RegCloseKey(hkey2);
+    }
     return ERROR_SUCCESS;
 }
 
@@ -4511,13 +4616,15 @@
     UINT rc = ERROR_SUCCESS; 
 
     if (MSI_RecordIsNull(row,2))
-        rc = register_progid_base(row,clsid);
+        rc = register_progid_base(package,row,clsid);
     else
     {
         WCHAR buffer[0x1000];
         DWORD sz, disp;
         HKEY hkey,hkey2;
         static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
+        static const WCHAR szDefaultIcon[] = {
+                'D','e','f','a','u','l','t','I','c','o','n',0};
 
         /* check if already registered */
         sz = 0x100;
@@ -4530,6 +4637,11 @@
             RegCloseKey(hkey);
             return rc;
         }
+
+        sz = 0x100;
+        MSI_RecordGetStringW(row,2,buffer,&sz);
+        rc = register_parent_progid(package,buffer,clsid);
+
         /* clsid is same as parent */
         RegCreateKeyW(hkey,szCLSID,&hkey2);
         RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
@@ -4537,9 +4649,6 @@
 
         RegCloseKey(hkey2);
 
-        sz = 0x100;
-        MSI_RecordGetStringW(row,2,buffer,&sz);
-        rc = register_parent_progid(package,buffer,clsid);
 
         if (!MSI_RecordIsNull(row,4))
         {
@@ -4550,7 +4659,17 @@
         }
 
         if (!MSI_RecordIsNull(row,5))
-            FIXME ("UNHANDLED icon in Progid\n");
+        {
+            LPWSTR FileName = load_dynamic_stringW(row,5);
+            LPWSTR FilePath;
+            RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
+            build_icon_path(package,FileName,&FilePath);
+            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)FilePath,
+                           (strlenW(FilePath)+1) * sizeof(WCHAR));
+            HeapFree(GetProcessHeap(),0,FilePath);
+            HeapFree(GetProcessHeap(),0,FileName);
+            RegCloseKey(hkey2);
+        }
 
         RegCloseKey(hkey);
     }
@@ -4847,6 +4966,29 @@
         'S','E','L','E','C','T',' ','*',' ',
         'f','r','o','m',' ','I','c','o','n',0};
     DWORD sz;
+    /* for registry stuff */
+    LPWSTR productcode;
+    WCHAR squished_pc[0x100];
+    HKEY hkey=0,hkey2=0,hkey3=0;
+    HKEY hukey=0,hukey2=0,hukey3=0;
+    static const WCHAR szProductCode[]=
+         {'P','r','o','d','u','c','t','C','o','d','e',0};
+    static const WCHAR szInstaller[] = {
+         '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',0 };
+    static const WCHAR szUserInstaller[] = {
+         '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',0 };
+    static const WCHAR szProducts[] = {
+         'P','r','o','d','u','c','t','s',0};
+    static const WCHAR szProductName[] = {
+         'P','r','o','d','u','c','t','N','a','m','e',0};
+    LPWSTR buffer;
+    DWORD size;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -4924,6 +5066,53 @@
     }
     MSI_ViewClose(view);
     msiobj_release(&view->hdr);
+
+    /* ok there is alot more done here but i need to figure out what */
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
+
+    squash_guid(productcode,squished_pc);
+
+    rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(HKEY_CURRENT_USER,szUserInstaller,&hukey);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hkey,szProducts,&hkey2);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hukey,szProducts,&hukey2);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hukey2,squished_pc,&hukey3);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    buffer = load_dynamic_property(package,szProductName,NULL);
+    size = strlenW(buffer)*sizeof(WCHAR);
+    RegSetValueExW(hukey3,szProductName,0,REG_SZ, (LPSTR)buffer,size);
+    HeapFree(GetProcessHeap(),0,buffer);
+ 
+end:
+
+    HeapFree(GetProcessHeap(),0,productcode);    
+    RegCloseKey(hkey3);
+    RegCloseKey(hkey2);
+    RegCloseKey(hkey);
+    RegCloseKey(hukey3);
+    RegCloseKey(hukey2);
+    RegCloseKey(hukey);
+
     return rc;
 
 }
@@ -5072,6 +5261,188 @@
     return rc;
 }
 
+static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
+{
+    UINT rc;
+    MSIQUERY * view;
+    MSIRECORD * row = 0;
+    static const WCHAR ExecSeqQuery[] = {'S','e','l','e','c','t',' ','*',' ',
+'f','r','o','m',' ','S','e','l','f','R','e','g',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+    {
+        TRACE("no SelfReg table\n");
+        return ERROR_SUCCESS;
+    }
+
+    rc = MSI_ViewExecute(view, 0);
+    if (rc != ERROR_SUCCESS)
+    {
+        MSI_ViewClose(view);
+        msiobj_release(&view->hdr);
+        return rc;
+    }
+
+    while (1)
+    {
+        LPWSTR filename;
+        INT index;
+        HMODULE dll;
+        DllRegisterServer* regfunc;
+
+        rc = MSI_ViewFetch(view,&row);
+        if (rc != ERROR_SUCCESS)
+        {
+            rc = ERROR_SUCCESS;
+            break;
+        }
+
+        filename = load_dynamic_stringW(row,1);
+        index = get_loaded_file(package,filename);
+
+        if (index < 0)
+        {
+            ERR("Unable to find file id %s\n",debugstr_w(filename));
+            HeapFree(GetProcessHeap(),0,filename);
+            msiobj_release(&row->hdr);
+            continue;
+        }
+        HeapFree(GetProcessHeap(),0,filename);
+
+        dll = LoadLibraryW(package->files[index].TargetPath);
+        if (!dll)
+        {
+            ERR("Unable to load dll %s\n",
+                    debugstr_w(package->files[index].TargetPath));
+            msiobj_release(&row->hdr);
+            continue;
+        }
+
+        regfunc = (DllRegisterServer*)GetProcAddress(dll,"DllRegisterServer");
+
+        if (regfunc)
+            regfunc();
+
+        msiobj_release(&row->hdr);
+    }
+    MSI_ViewClose(view);
+    msiobj_release(&view->hdr);
+    return rc;
+}
+
+static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
+{
+    LPWSTR productcode;
+    WCHAR squished_pc[0x100];
+    UINT rc;
+    DWORD i;
+    HKEY hkey=0,hkey2=0,hkey3=0;
+    HKEY hukey=0,hukey2=0,hukey3=0;
+    static const WCHAR szProductCode[]=
+         {'P','r','o','d','u','c','t','C','o','d','e',0};
+    static const WCHAR szInstaller[] = {
+         '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',0 };
+    static const WCHAR szUserInstaller[] = {
+         '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',0 };
+    static const WCHAR szFeatures[] = {
+         'F','e','a','t','u','r','e','s',0 };
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    productcode = load_dynamic_property(package,szProductCode,&rc);
+    if (!productcode)
+        return rc;
+
+    squash_guid(productcode,squished_pc);
+    rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(HKEY_CURRENT_USER,szUserInstaller,&hukey);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hkey,szFeatures,&hkey2);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hukey,szFeatures,&hukey2);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hkey2,squished_pc,&hkey3);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegCreateKeyW(hukey2,squished_pc,&hukey3);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    /* here the guids are base 85 encoded */
+    for (i = 0; i < package->loaded_features; i++)
+    {
+        LPWSTR data = NULL;
+        GUID clsid;
+        int j;
+        INT size;
+
+        size = package->features[i].ComponentCount*21;
+        size +=1;
+        if (package->features[i].Feature_Parent[0])
+            size += strlenW(package->features[i].Feature_Parent)+2;
+
+        data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+
+        data[0] = 0;
+        for (j = 0; j < package->features[i].ComponentCount; j++)
+        {
+            WCHAR buf[21];
+            memset(buf,0,sizeof(buf));
+            TRACE("From %s\n",debugstr_w(package->components
+                            [package->features[i].Components[j]].ComponentId));
+            CLSIDFromString(package->components
+                            [package->features[i].Components[j]].ComponentId,
+                            &clsid);
+            encode_base85_guid(&clsid,buf);
+            TRACE("to %s\n",debugstr_w(buf));
+            strcatW(data,buf);
+        }
+        if (package->features[i].Feature_Parent[0])
+        {
+            static const WCHAR sep[] = {'\2',0};
+            strcatW(data,sep);
+            strcatW(data,package->features[i].Feature_Parent);
+        }
+
+        size = (strlenW(data)+2)*sizeof(WCHAR);
+        RegSetValueExW(hkey3,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)data,size);
+        HeapFree(GetProcessHeap(),0,data);
+
+        size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
+        RegSetValueExW(hukey3,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)package->features[i].Feature_Parent,size);
+    }
+
+    RegCloseKey(hkey3);
+    RegCloseKey(hukey3);
+end:
+    HeapFree(GetProcessHeap(), 0, productcode);
+    RegCloseKey(hkey2);
+    RegCloseKey(hukey2);
+    RegCloseKey(hkey);
+    RegCloseKey(hukey);
+    return rc;
+}
+
 /* Msi functions that seem appropriate here */
 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
 {
@@ -5554,21 +5925,21 @@
     MSIRECORD * row = 0;
     static const WCHAR ExecSeqQuery[] = {0};
 
-    rc = MsiDatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
     if (rc != ERROR_SUCCESS)
         return rc;
 
-    rc = MsiViewExecute(view, 0);
+    rc = MSI_ViewExecute(view, 0);
     if (rc != ERROR_SUCCESS)
     {
-        MsiViewClose(view);
+        MSI_ViewClose(view);
         msiobj_release(&view->hdr);
         return rc;
     }
 
     while (1)
     {
-        rc = MsiViewFetch(view,&row);
+        rc = MSI_ViewFetch(view,&row);
         if (rc != ERROR_SUCCESS)
         {
             rc = ERROR_SUCCESS;
@@ -5577,7 +5948,7 @@
 
         msiobj_release(&row->hdr);
     }
-    MsiViewClose(view);
+    MSI_ViewClose(view);
     msiobj_release(&view->hdr);
     return rc;
 }


More information about the wine-patches mailing list