msi: resubmit breakup, class registeration functions

Aric Stewart aric at codeweavers.com
Thu Jun 16 07:50:43 CDT 2005


Mondo patch Part 2:
Break out all the class registration actions into classes.c
This includes RegisterClassInfo, RegisterProgIds, RegisterExtensions and 
RegisterMIMETypes
-------------- next part --------------
Index: dlls/msi/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/msi/Makefile.in,v
retrieving revision 1.29
diff -u -r1.29 Makefile.in
--- dlls/msi/Makefile.in	15 Jun 2005 19:12:43 -0000	1.29
+++ dlls/msi/Makefile.in	16 Jun 2005 12:45:41 -0000
@@ -10,6 +10,7 @@
 C_SRCS = \
 	action.c \
 	appsearch.c \
+	classes.c \
 	create.c \
 	custom.c \
 	database.c \
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.146
diff -u -r1.146 action.c
--- dlls/msi/action.c	15 Jun 2005 19:12:42 -0000	1.146
+++ dlls/msi/action.c	16 Jun 2005 12:45:43 -0000
@@ -80,10 +80,6 @@
 static UINT ACTION_InstallValidate(MSIPACKAGE *package);
 static UINT ACTION_ProcessComponents(MSIPACKAGE *package);
 static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package);
-static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
-static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
 static UINT ACTION_RegisterUser(MSIPACKAGE *package);
 static UINT ACTION_CreateShortcuts(MSIPACKAGE *package);
 static UINT ACTION_PublishProduct(MSIPACKAGE *package);
@@ -129,12 +125,12 @@
     {'L','a','u','n','c','h','C','o','n','d','i','t','i','o','n','s',0};
 const static WCHAR szProcessComponents[] = 
     {'P','r','o','c','e','s','s','C','o','m','p','o','n','e','n','t','s',0};
-const static WCHAR szRegisterTypeLibraries[] = 
+const WCHAR szRegisterTypeLibraries[] = 
     {'R','e','g','i','s','t','e','r','T','y','p','e',
             'L','i','b','r','a','r','i','e','s',0};
-const static WCHAR szRegisterClassInfo[] = 
+const WCHAR szRegisterClassInfo[] = 
     {'R','e','g','i','s','t','e','r','C','l','a','s','s','I','n','f','o',0};
-const static WCHAR szRegisterProgIdInfo[] = 
+const WCHAR szRegisterProgIdInfo[] = 
     {'R','e','g','i','s','t','e','r','P','r','o','g','I','d','I','n','f','o',0};
 const static WCHAR szCreateShortcuts[] = 
     {'C','r','e','a','t','e','S','h','o','r','t','c','u','t','s',0};
@@ -159,7 +155,7 @@
     {'F','o','r','c','e','R','e','b','o','o','t',0};
 const static WCHAR szResolveSource[] =
     {'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
-const static WCHAR szAppSearch[] = 
+const WCHAR szAppSearch[] = 
     {'A','p','p','S','e','a','r','c','h',0};
 const static WCHAR szAllocateRegistrySpace[] = 
     {'A','l','l','o','c','a','t','e','R','e','g','i','s','t','r','y',
@@ -174,7 +170,7 @@
     {'D','i','s','a','b','l','e','R','o','l','l','b','a','c','k',0};
 const static WCHAR szExecuteAction[] = 
     {'E','x','e','c','u','t','e','A','c','t','i','o','n',0};
-const static WCHAR szFindRelatedProducts[] = 
+const WCHAR szFindRelatedProducts[] = 
     {'F','i','n','d','R','e','l','a','t','e','d',
             'P','r','o','d','u','c','t','s',0};
 const static WCHAR szInstallAdminPackage[] = 
@@ -206,12 +202,12 @@
     {'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t','s',0};
 const static WCHAR szRegisterComPlus[] =
     {'R','e','g','i','s','t','e','r','C','o','m','P','l','u','s',0};
-const static WCHAR szRegisterExtensionInfo[] =
+const WCHAR szRegisterExtensionInfo[] =
     {'R','e','g','i','s','t','e','r','E','x','t','e','n','s','i','o','n',
             'I','n','f','o',0};
 const static WCHAR szRegisterFonts[] =
     {'R','e','g','i','s','t','e','r','F','o','n','t','s',0};
-const static WCHAR szRegisterMIMEInfo[] =
+const WCHAR szRegisterMIMEInfo[] =
     {'R','e','g','i','s','t','e','r','M','I','M','E','I','n','f','o',0};
 const static WCHAR szRegisterUser[] =
     {'R','e','g','i','s','t','e','r','U','s','e','r',0};
@@ -3625,1267 +3621,6 @@
     return rc;
 }
 
-static INT load_appid(MSIPACKAGE* package, MSIRECORD *row)
-{
-    DWORD index = package->loaded_appids;
-    DWORD sz;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_appids++;
-    if (package->loaded_appids == 1)
-        package->appids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIAPPID));
-    else
-        package->appids = HeapReAlloc(GetProcessHeap(),0,
-            package->appids, package->loaded_appids * sizeof(MSIAPPID));
-
-    memset(&package->appids[index],0,sizeof(MSIAPPID));
-    
-    sz = IDENTIFIER_SIZE;
-    MSI_RecordGetStringW(row, 1, package->appids[index].AppID, &sz);
-    TRACE("loading appid %s\n",debugstr_w(package->appids[index].AppID));
-
-    buffer = MSI_RecordGetString(row,2);
-    deformat_string(package,buffer,&package->appids[index].RemoteServerName);
-
-    package->appids[index].LocalServer = load_dynamic_stringW(row,3);
-    package->appids[index].ServiceParameters = load_dynamic_stringW(row,4);
-    package->appids[index].DllSurrogate = load_dynamic_stringW(row,5);
-
-    package->appids[index].ActivateAtStorage = !MSI_RecordIsNull(row,6);
-    package->appids[index].RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
-    
-    return index;
-}
-
-static INT load_given_appid(MSIPACKAGE *package, LPCWSTR appid)
-{
-    INT rc;
-    MSIRECORD *row;
-    INT i;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','A','p','p','I','d','`',' ','W','H','E','R','E',' ',
-         '`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0};
-
-    if (!appid)
-        return -1;
-
-    /* check for appids already loaded */
-    for (i = 0; i < package->loaded_appids; i++)
-        if (strcmpiW(package->appids[i].AppID,appid)==0)
-        {
-            TRACE("found appid %s at index %i\n",debugstr_w(appid),i);
-            return i;
-        }
-    
-    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, appid);
-    if (!row)
-        return -1;
-
-    rc = load_appid(package, row);
-    msiobj_release(&row->hdr);
-
-    return rc;
-}
-
-static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
-static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid);
-
-static INT load_progid(MSIPACKAGE* package, MSIRECORD *row)
-{
-    DWORD index = package->loaded_progids;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_progids++;
-    if (package->loaded_progids == 1)
-        package->progids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIPROGID));
-    else
-        package->progids = HeapReAlloc(GetProcessHeap(),0,
-            package->progids , package->loaded_progids * sizeof(MSIPROGID));
-
-    memset(&package->progids[index],0,sizeof(MSIPROGID));
-
-    package->progids[index].ProgID = load_dynamic_stringW(row,1);
-    TRACE("loading progid %s\n",debugstr_w(package->progids[index].ProgID));
-
-    buffer = MSI_RecordGetString(row,2);
-    package->progids[index].ParentIndex = load_given_progid(package,buffer);
-    if (package->progids[index].ParentIndex < 0 && buffer)
-        FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
-
-    buffer = MSI_RecordGetString(row,3);
-    package->progids[index].ClassIndex = load_given_class(package,buffer);
-    if (package->progids[index].ClassIndex< 0 && buffer)
-        FIXME("Unknown class %s\n",debugstr_w(buffer));
-
-    package->progids[index].Description = load_dynamic_stringW(row,4);
-
-    if (!MSI_RecordIsNull(row,6))
-    {
-        INT icon_index = MSI_RecordGetInteger(row,6); 
-        LPWSTR FileName = load_dynamic_stringW(row,5);
-        LPWSTR FilePath;
-        static const WCHAR fmt[] = {'%','s',',','%','i',0};
-
-        build_icon_path(package,FileName,&FilePath);
-       
-        package->progids[index].IconPath = 
-                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+10)*
-                                sizeof(WCHAR));
-
-        sprintfW(package->progids[index].IconPath,fmt,FilePath,icon_index);
-
-        HeapFree(GetProcessHeap(),0,FilePath);
-        HeapFree(GetProcessHeap(),0,FileName);
-    }
-    else
-    {
-        buffer = MSI_RecordGetString(row,5);
-        if (buffer)
-            build_icon_path(package,buffer,&(package->progids[index].IconPath));
-    }
-
-    package->progids[index].CurVerIndex = -1;
-    package->progids[index].VersionIndIndex = -1;
-
-    /* if we have a parent then we may be that parents CurVer */
-    if (package->progids[index].ParentIndex >= 0 && 
-        package->progids[index].ParentIndex != index)
-    {
-        int pindex = package->progids[index].ParentIndex;
-        while (package->progids[pindex].ParentIndex>= 0)
-            pindex = package->progids[pindex].ParentIndex;
-
-        FIXME("BAD BAD need to determing if we are really the CurVer\n");
-
-        package->progids[index].CurVerIndex = pindex;
-        package->progids[pindex].VersionIndIndex = index;
-    }
-    
-    return index;
-}
-
-static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid)
-{
-    INT rc;
-    MSIRECORD *row;
-    INT i;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ',
-         '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
-
-    if (!progid)
-        return -1;
-
-    /* check for progids already loaded */
-    for (i = 0; i < package->loaded_progids; i++)
-        if (strcmpiW(package->progids[i].ProgID,progid)==0)
-        {
-            TRACE("found progid %s at index %i\n",debugstr_w(progid), i);
-            return i;
-        }
-    
-    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, progid);
-    if(!row)
-        return -1;
-
-    rc = load_progid(package, row);
-    msiobj_release(&row->hdr);
-
-    return rc;
-}
-
-static INT load_class(MSIPACKAGE* package, MSIRECORD *row)
-{
-    DWORD index = package->loaded_classes;
-    DWORD sz,i;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_classes++;
-    if (package->loaded_classes== 1)
-        package->classes = HeapAlloc(GetProcessHeap(),0,sizeof(MSICLASS));
-    else
-        package->classes = HeapReAlloc(GetProcessHeap(),0,
-            package->classes, package->loaded_classes * sizeof(MSICLASS));
-
-    memset(&package->classes[index],0,sizeof(MSICLASS));
-
-    sz = IDENTIFIER_SIZE;
-    MSI_RecordGetStringW(row, 1, package->classes[index].CLSID, &sz);
-    TRACE("loading class %s\n",debugstr_w(package->classes[index].CLSID));
-    sz = IDENTIFIER_SIZE;
-    MSI_RecordGetStringW(row, 2, package->classes[index].Context, &sz);
-    buffer = MSI_RecordGetString(row,3);
-    package->classes[index].ComponentIndex = get_loaded_component(package, 
-                    buffer);
-
-    package->classes[index].ProgIDText = load_dynamic_stringW(row,4);
-    package->classes[index].ProgIDIndex = 
-                load_given_progid(package, package->classes[index].ProgIDText);
-
-    package->classes[index].Description = load_dynamic_stringW(row,5);
-
-    buffer = MSI_RecordGetString(row,6);
-    if (buffer)
-        package->classes[index].AppIDIndex = 
-                load_given_appid(package, buffer);
-    else
-        package->classes[index].AppIDIndex = -1;
-
-    package->classes[index].FileTypeMask = load_dynamic_stringW(row,7);
-
-    if (!MSI_RecordIsNull(row,9))
-    {
-
-        INT icon_index = MSI_RecordGetInteger(row,9); 
-        LPWSTR FileName = load_dynamic_stringW(row,8);
-        LPWSTR FilePath;
-        static const WCHAR fmt[] = {'%','s',',','%','i',0};
-
-        build_icon_path(package,FileName,&FilePath);
-       
-        package->classes[index].IconPath = 
-                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
-                                sizeof(WCHAR));
-
-        sprintfW(package->classes[index].IconPath,fmt,FilePath,icon_index);
-
-        HeapFree(GetProcessHeap(),0,FilePath);
-        HeapFree(GetProcessHeap(),0,FileName);
-    }
-    else
-    {
-        buffer = MSI_RecordGetString(row,8);
-        if (buffer)
-            build_icon_path(package,buffer,&(package->classes[index].IconPath));
-    }
-
-    if (!MSI_RecordIsNull(row,10))
-    {
-        i = MSI_RecordGetInteger(row,10);
-        if (i != MSI_NULL_INTEGER && i > 0 &&  i < 4)
-        {
-            static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
-            static const WCHAR ole32[] = {'o','l','e','3','2','.','d','l','l',0};
-
-            switch(i)
-            {
-                case 1:
-                    package->classes[index].DefInprocHandler = strdupW(ole2);
-                    break;
-                case 2:
-                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
-                    break;
-                case 3:
-                    package->classes[index].DefInprocHandler = strdupW(ole2);
-                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
-                    break;
-            }
-        }
-        else
-        {
-            package->classes[index].DefInprocHandler32 = load_dynamic_stringW(
-                            row, 10);
-            reduce_to_longfilename(package->classes[index].DefInprocHandler32);
-        }
-    }
-    buffer = MSI_RecordGetString(row,11);
-    deformat_string(package,buffer,&package->classes[index].Argument);
-
-    buffer = MSI_RecordGetString(row,12);
-    package->classes[index].FeatureIndex = get_loaded_feature(package,buffer);
-
-    package->classes[index].Attributes = MSI_RecordGetInteger(row,13);
-    
-    return index;
-}
-
-/*
- * the Class table has 3 primary keys. Generally it is only 
- * referenced through the first CLSID key. However when loading
- * all of the classes we need to make sure we do not ignore rows
- * with other Context and ComponentIndexs 
- */
-static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid)
-{
-    INT rc;
-    MSIRECORD *row;
-    INT i;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','C','l','a','s','s','`',' ','W','H','E','R','E',' ',
-         '`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0};
-
-
-    if (!classid)
-        return -1;
-    
-    /* check for classes already loaded */
-    for (i = 0; i < package->loaded_classes; i++)
-        if (strcmpiW(package->classes[i].CLSID,classid)==0)
-        {
-            TRACE("found class %s at index %i\n",debugstr_w(classid), i);
-            return i;
-        }
-    
-    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, classid);
-    if (!row)
-        return -1;
-
-    rc = load_class(package, row);
-    msiobj_release(&row->hdr);
-
-    return rc;
-}
-
-static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension);
-
-static INT load_mime(MSIPACKAGE* package, MSIRECORD *row)
-{
-    DWORD index = package->loaded_mimes;
-    DWORD sz;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_mimes++;
-    if (package->loaded_mimes== 1)
-        package->mimes= HeapAlloc(GetProcessHeap(),0,sizeof(MSIMIME));
-    else
-        package->mimes= HeapReAlloc(GetProcessHeap(),0,
-            package->mimes, package->loaded_mimes* 
-            sizeof(MSIMIME));
-
-    memset(&package->mimes[index],0,sizeof(MSIMIME));
-
-    package->mimes[index].ContentType = load_dynamic_stringW(row,1); 
-    TRACE("loading mime %s\n",debugstr_w(package->mimes[index].ContentType));
-
-    buffer = MSI_RecordGetString(row,2);
-    package->mimes[index].ExtensionIndex = load_given_extension(package,
-                    buffer);
-
-    sz = IDENTIFIER_SIZE;
-    MSI_RecordGetStringW(row,3,package->mimes[index].CLSID,&sz);
-    package->mimes[index].ClassIndex= load_given_class(package,
-                    package->mimes[index].CLSID);
-    
-    return index;
-}
-
-static INT load_given_mime(MSIPACKAGE *package, LPCWSTR mime)
-{
-    INT rc;
-    MSIRECORD *row;
-    INT i;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','M','I','M','E','`',' ','W','H','E','R','E',' ',
-         '`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ',
-         '\'','%','s','\'',0};
-
-    if (!mime)
-        return -1;
-    
-    /* check for mime already loaded */
-    for (i = 0; i < package->loaded_mimes; i++)
-        if (strcmpiW(package->mimes[i].ContentType,mime)==0)
-        {
-            TRACE("found mime %s at index %i\n",debugstr_w(mime), i);
-            return i;
-        }
-    
-    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, mime);
-    if (!row)
-        return -1;
-
-    rc = load_mime(package, row);
-    msiobj_release(&row->hdr);
-
-    return rc;
-}
-
-static INT load_extension(MSIPACKAGE* package, MSIRECORD *row)
-{
-    DWORD index = package->loaded_extensions;
-    DWORD sz;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_extensions++;
-    if (package->loaded_extensions == 1)
-        package->extensions = HeapAlloc(GetProcessHeap(),0,sizeof(MSIEXTENSION));
-    else
-        package->extensions = HeapReAlloc(GetProcessHeap(),0,
-            package->extensions, package->loaded_extensions* 
-            sizeof(MSIEXTENSION));
-
-    memset(&package->extensions[index],0,sizeof(MSIEXTENSION));
-
-    sz = 256;
-    MSI_RecordGetStringW(row,1,package->extensions[index].Extension,&sz);
-    TRACE("loading extension %s\n",
-                    debugstr_w(package->extensions[index].Extension));
-
-    buffer = MSI_RecordGetString(row,2);
-    package->extensions[index].ComponentIndex = 
-            get_loaded_component(package,buffer);
-
-    package->extensions[index].ProgIDText = load_dynamic_stringW(row,3);
-    package->extensions[index].ProgIDIndex = load_given_progid(package,
-                    package->extensions[index].ProgIDText);
-
-    buffer = MSI_RecordGetString(row,4);
-    package->extensions[index].MIMEIndex = load_given_mime(package,buffer);
-
-    buffer = MSI_RecordGetString(row,5);
-    package->extensions[index].FeatureIndex = 
-            get_loaded_feature(package,buffer);
-
-    return index;
-}
-
-/*
- * While the extension table has 2 primary keys, this function is only looking
- * at the Extension key which is what is referenced as a forign key 
- */
-static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension)
-{
-    INT rc;
-    MSIRECORD *row;
-    INT i;
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','E','x','t','e','n','s','i','o','n','`',' ',
-         'W','H','E','R','E',' ',
-         '`','E','x','t','e','n','s','i','o','n','`',' ','=',' ',
-         '\'','%','s','\'',0};
-
-    if (!extension)
-        return -1;
-
-    /* check for extensions already loaded */
-    for (i = 0; i < package->loaded_extensions; i++)
-        if (strcmpiW(package->extensions[i].Extension,extension)==0)
-        {
-            TRACE("extension %s already loaded at %i\n",debugstr_w(extension),
-                            i);
-            return i;
-        }
-    
-    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, extension);
-    if (!row)
-        return -1;
-
-    rc = load_extension(package, row);
-    msiobj_release(&row->hdr);
-
-    return rc;
-}
-
-static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
-{
-    MSIPACKAGE* package = (MSIPACKAGE*)param;
-    DWORD index = package->loaded_verbs;
-    LPCWSTR buffer;
-
-    /* fill in the data */
-
-    package->loaded_verbs++;
-    if (package->loaded_verbs == 1)
-        package->verbs = HeapAlloc(GetProcessHeap(),0,sizeof(MSIVERB));
-    else
-        package->verbs = HeapReAlloc(GetProcessHeap(),0,
-            package->verbs , package->loaded_verbs * sizeof(MSIVERB));
-
-    memset(&package->verbs[index],0,sizeof(MSIVERB));
-
-    buffer = MSI_RecordGetString(row,1);
-    package->verbs[index].ExtensionIndex = load_given_extension(package,buffer);
-    if (package->verbs[index].ExtensionIndex < 0 && buffer)
-        ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
-
-    package->verbs[index].Verb = load_dynamic_stringW(row,2);
-    TRACE("loading verb %s\n",debugstr_w(package->verbs[index].Verb));
-    package->verbs[index].Sequence = MSI_RecordGetInteger(row,3);
-
-    buffer = MSI_RecordGetString(row,4);
-    deformat_string(package,buffer,&package->verbs[index].Command);
-
-    buffer = MSI_RecordGetString(row,5);
-    deformat_string(package,buffer,&package->verbs[index].Argument);
-
-    /* assosiate the verb with the correct extension */
-    if (package->verbs[index].ExtensionIndex >= 0)
-    {
-        MSIEXTENSION* extension = &package->extensions[package->verbs[index].
-                ExtensionIndex];
-        int count = extension->VerbCount;
-
-        if (count >= 99)
-            FIXME("Exceeding max verb count! Increase that limit!!!\n");
-        else
-        {
-            extension->VerbCount++;
-            extension->Verbs[count] = index;
-        }
-    }
-    
-    return ERROR_SUCCESS;
-}
-
-static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
-{
-    LPCWSTR clsid;
-    LPCWSTR context;
-    LPCWSTR buffer;
-    INT    component_index;
-    MSIPACKAGE* package =(MSIPACKAGE*)param;
-    INT i;
-    BOOL match = FALSE;
-
-    clsid = MSI_RecordGetString(rec,1);
-    context = MSI_RecordGetString(rec,2);
-    buffer = MSI_RecordGetString(rec,3);
-    component_index = get_loaded_component(package,buffer);
-
-    for (i = 0; i < package->loaded_classes; i++)
-    {
-        if (strcmpiW(clsid,package->classes[i].CLSID))
-            continue;
-        if (strcmpW(context,package->classes[i].Context))
-            continue;
-        if (component_index == package->classes[i].ComponentIndex)
-        {
-            match = TRUE;
-            break;
-        }
-    }
-    
-    if (!match)
-        load_class(package, rec);
-
-    return ERROR_SUCCESS;
-}
-
-static VOID load_all_classes(MSIPACKAGE *package)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIQUERY *view;
-
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
-         '`','C','l','a','s','s','`',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return;
-
-    rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
-    msiobj_release(&view->hdr);
-}
-
-static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
-{
-    LPCWSTR buffer;
-    LPCWSTR extension;
-    INT    component_index;
-    MSIPACKAGE* package =(MSIPACKAGE*)param;
-    BOOL match = FALSE;
-    INT i;
-
-    extension = MSI_RecordGetString(rec,1);
-    buffer = MSI_RecordGetString(rec,2);
-    component_index = get_loaded_component(package,buffer);
-
-    for (i = 0; i < package->loaded_extensions; i++)
-    {
-        if (strcmpiW(extension,package->extensions[i].Extension))
-            continue;
-        if (component_index == package->extensions[i].ComponentIndex)
-        {
-            match = TRUE;
-            break;
-        }
-    }
-
-    if (!match)
-        load_extension(package, rec);
-
-    return ERROR_SUCCESS;
-}
-
-static VOID load_all_extensions(MSIPACKAGE *package)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIQUERY *view;
-
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','E','x','t','e','n','s','i','o','n','`',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return;
-
-    rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
-    msiobj_release(&view->hdr);
-}
-
-static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
-{
-    LPCWSTR buffer;
-    MSIPACKAGE* package =(MSIPACKAGE*)param;
-
-    buffer = MSI_RecordGetString(rec,1);
-    load_given_progid(package,buffer);
-    return ERROR_SUCCESS;
-}
-
-static VOID load_all_progids(MSIPACKAGE *package)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIQUERY *view;
-
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ',
-         'F','R','O','M',' ', '`','P','r','o','g','I','d','`',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return;
-
-    rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
-    msiobj_release(&view->hdr);
-}
-
-static VOID load_all_verbs(MSIPACKAGE *package)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIQUERY *view;
-
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
-         '`','V','e','r','b','`',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return;
-
-    rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
-    msiobj_release(&view->hdr);
-}
-
-static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
-{
-    LPCWSTR buffer;
-    MSIPACKAGE* package =(MSIPACKAGE*)param;
-
-    buffer = MSI_RecordGetString(rec,1);
-    load_given_mime(package,buffer);
-    return ERROR_SUCCESS;
-}
-
-static VOID load_all_mimes(MSIPACKAGE *package)
-{
-    UINT rc = ERROR_SUCCESS;
-    MSIQUERY *view;
-
-    static const WCHAR ExecSeqQuery[] =
-        {'S','E','L','E','C','T',' ',
-         '`','C','o','n','t','e','n','t','T','y','p','e','`',
-         ' ','F','R','O','M',' ',
-         '`','M','I','M','E','`',0};
-
-    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
-    if (rc != ERROR_SUCCESS)
-        return;
-
-    rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
-    msiobj_release(&view->hdr);
-}
-
-static void load_classes_and_such(MSIPACKAGE *package)
-{
-    TRACE("Loading all the class info and related tables\n");
-
-    /* check if already loaded */
-    if (package->classes || package->extensions || package->progids || 
-        package->verbs || package->mimes)
-        return;
-
-    load_all_classes(package);
-    load_all_extensions(package);
-    load_all_progids(package);
-    /* these loads must come after the other loads */
-    load_all_verbs(package);
-    load_all_mimes(package);
-}
-
-static void mark_progid_for_install(MSIPACKAGE* package, INT index)
-{
-    MSIPROGID* progid;
-    int i;
-
-    if (index < 0 || index >= package->loaded_progids)
-        return;
-
-    progid = &package->progids[index];
-
-    if (progid->InstallMe == TRUE)
-        return;
-
-    progid->InstallMe = TRUE;
-
-    /* all children if this is a parent also install */
-   for (i = 0; i < package->loaded_progids; i++)
-        if (package->progids[i].ParentIndex == index)
-            mark_progid_for_install(package,i);
-}
-
-static void mark_mime_for_install(MSIPACKAGE* package, INT index)
-{
-    MSIMIME* mime;
-
-    if (index < 0 || index >= package->loaded_mimes)
-        return;
-
-    mime = &package->mimes[index];
-
-    if (mime->InstallMe == TRUE)
-        return;
-
-    mime->InstallMe = TRUE;
-}
-
-static UINT register_appid(MSIPACKAGE *package, int appidIndex, LPCWSTR app )
-{
-    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
-    HKEY hkey2,hkey3;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
-    RegCreateKeyW(hkey2,package->appids[appidIndex].AppID,&hkey3);
-    RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
-                   (strlenW(app)+1)*sizeof(WCHAR));
-
-    if (package->appids[appidIndex].RemoteServerName)
-    {
-        UINT size; 
-        static const WCHAR szRemoteServerName[] =
-             {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',
-              0};
-
-        size = (strlenW(package->appids[appidIndex].RemoteServerName)+1) * 
-                sizeof(WCHAR);
-
-        RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,
-                        (LPVOID)package->appids[appidIndex].RemoteServerName,
-                        size);
-    }
-
-    if (package->appids[appidIndex].LocalServer)
-    {
-        static const WCHAR szLocalService[] =
-             {'L','o','c','a','l','S','e','r','v','i','c','e',0};
-        UINT size;
-        size = (strlenW(package->appids[appidIndex].LocalServer)+1) * 
-                sizeof(WCHAR);
-
-        RegSetValueExW(hkey3,szLocalService,0,REG_SZ,
-                        (LPVOID)package->appids[appidIndex].LocalServer,size);
-    }
-
-    if (package->appids[appidIndex].ServiceParameters)
-    {
-        static const WCHAR szService[] =
-             {'S','e','r','v','i','c','e',
-              'P','a','r','a','m','e','t','e','r','s',0};
-        UINT size;
-        size = (strlenW(package->appids[appidIndex].ServiceParameters)+1) * 
-                sizeof(WCHAR);
-        RegSetValueExW(hkey3,szService,0,REG_SZ,
-                        (LPVOID)package->appids[appidIndex].ServiceParameters,
-                        size);
-    }
-
-    if (package->appids[appidIndex].DllSurrogate)
-    {
-        static const WCHAR szDLL[] =
-             {'D','l','l','S','u','r','r','o','g','a','t','e',0};
-        UINT size;
-        size = (strlenW(package->appids[appidIndex].DllSurrogate)+1) * 
-                sizeof(WCHAR);
-        RegSetValueExW(hkey3,szDLL,0,REG_SZ,
-                        (LPVOID)package->appids[appidIndex].DllSurrogate,size);
-    }
-
-    if (package->appids[appidIndex].ActivateAtStorage)
-    {
-        static const WCHAR szActivate[] =
-             {'A','c','t','i','v','a','t','e','A','s',
-              'S','t','o','r','a','g','e',0};
-        static const WCHAR szY[] = {'Y',0};
-
-        RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
-    }
-
-    if (package->appids[appidIndex].RunAsInteractiveUser)
-    {
-        static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
-        static const WCHAR szUser[] = 
-             {'I','n','t','e','r','a','c','t','i','v','e',' ',
-              'U','s','e','r',0};
-
-        RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,sizeof(szUser));
-    }
-
-    RegCloseKey(hkey3);
-    RegCloseKey(hkey2);
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
-{
-    /* 
-     * Again I am assuming the words, "Whose key file represents" when referring
-     * to a Component as to meaning that Components KeyPath file
-     */
-    
-    UINT rc;
-    MSIRECORD *uirow;
-    static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
-    static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
-    static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
-    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
-    static const WCHAR szSpace[] = {' ',0};
-    static const WCHAR szInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
-    static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
-    HKEY hkey,hkey2,hkey3;
-    BOOL install_on_demand = FALSE;
-    int i;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    load_classes_and_such(package);
-    rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
-    if (rc != ERROR_SUCCESS)
-        return ERROR_FUNCTION_FAILED;
-
-    /* install_on_demand should be set if OLE supports install on demand OLE
-     * servers. For now i am defaulting to FALSE because i do not know how to
-     * check, and i am told our builtin OLE does not support it
-     */
-    
-    for (i = 0; i < package->loaded_classes; i++)
-    {
-        INT index,f_index;
-        DWORD size, sz;
-        LPWSTR argument;
-
-        if (package->classes[i].ComponentIndex < 0)
-        {
-            continue;
-        }
-
-        index = package->classes[i].ComponentIndex;
-        f_index = package->classes[i].FeatureIndex;
-
-        /* 
-         * yes. MSDN says that these are based on _Feature_ not on
-         * Component.  So verify the feature is to be installed
-         */
-        if ((!ACTION_VerifyFeatureForAction(package, f_index,
-                                INSTALLSTATE_LOCAL)) &&
-             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
-                             f_index, INSTALLSTATE_ADVERTISED)))
-        {
-            TRACE("Skipping class %s reg due to disabled feature %s\n", 
-                            debugstr_w(package->classes[i].CLSID), 
-                            debugstr_w(package->features[f_index].Feature));
-
-            continue;
-        }
-
-        TRACE("Registering index %i  class %s\n",i,
-                        debugstr_w(package->classes[i].CLSID));
-
-        package->classes[i].Installed = TRUE;
-        if (package->classes[i].ProgIDIndex >= 0)
-            mark_progid_for_install(package, package->classes[i].ProgIDIndex);
-
-        RegCreateKeyW(hkey,package->classes[i].CLSID,&hkey2);
-
-        if (package->classes[i].Description)
-            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)package->classes[i].
-                            Description, (strlenW(package->classes[i].
-                                     Description)+1)*sizeof(WCHAR));
-
-        RegCreateKeyW(hkey2,package->classes[i].Context,&hkey3);
-        index = get_loaded_file(package,package->components[index].KeyPath);
-
-
-        /* the context server is a short path name 
-         * except for if it is InprocServer32... 
-         */
-        if (strcmpiW(package->classes[i].Context,szInprocServer32)!=0)
-        {
-            sz = 0;
-            sz = GetShortPathNameW(package->files[index].TargetPath, NULL, 0);
-            if (sz == 0)
-            {
-                ERR("Unable to find short path for CLSID COM Server\n");
-                argument = NULL;
-            }
-            else
-            {
-                size = sz * sizeof(WCHAR);
-
-                if (package->classes[i].Argument)
-                {
-                    size += strlenW(package->classes[i].Argument) * 
-                            sizeof(WCHAR);
-                    size += sizeof(WCHAR);
-                }
-
-                argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
-                GetShortPathNameW(package->files[index].TargetPath, argument, 
-                                sz);
-
-                if (package->classes[i].Argument)
-                {
-                    strcatW(argument,szSpace);
-                    strcatW(argument,package->classes[i].Argument);
-                }
-            }
-        }
-        else
-        {
-            size = lstrlenW(package->files[index].TargetPath) * sizeof(WCHAR);
-
-            if (package->classes[i].Argument)
-            {
-                size += strlenW(package->classes[i].Argument) * sizeof(WCHAR);
-                size += sizeof(WCHAR);
-            }
-
-            argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
-            strcpyW(argument, package->files[index].TargetPath);
-
-            if (package->classes[i].Argument)
-            {
-                strcatW(argument,szSpace);
-                strcatW(argument,package->classes[i].Argument);
-            }
-        }
-
-        if (argument)
-        {
-            RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
-            HeapFree(GetProcessHeap(),0,argument);
-        }
-
-        RegCloseKey(hkey3);
-
-        if (package->classes[i].ProgIDIndex >= 0 || 
-            package->classes[i].ProgIDText)
-        {
-            LPCWSTR progid;
-
-            if (package->classes[i].ProgIDIndex >= 0)
-                progid = package->progids[
-                        package->classes[i].ProgIDIndex].ProgID;
-            else
-                progid = package->classes[i].ProgIDText;
-
-            RegCreateKeyW(hkey2,szProgID,&hkey3);
-            RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)progid,
-                            (strlenW(progid)+1) *sizeof(WCHAR));
-            RegCloseKey(hkey3);
-
-            if (package->classes[i].ProgIDIndex >= 0 &&
-                package->progids[package->classes[i].ProgIDIndex].
-                                VersionIndIndex >= 0)
-            {
-                LPWSTR viprogid = strdupW(package->progids[package->progids[
-                        package->classes[i].ProgIDIndex].VersionIndIndex].
-                        ProgID);
-                RegCreateKeyW(hkey2,szVIProgID,&hkey3);
-                RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)viprogid,
-                            (strlenW(viprogid)+1) *sizeof(WCHAR));
-                RegCloseKey(hkey3);
-                HeapFree(GetProcessHeap(), 0, viprogid);
-            }
-        }
-
-        if (package->classes[i].AppIDIndex >= 0)
-        { 
-            RegSetValueExW(hkey2,szAppID,0,REG_SZ,
-             (LPVOID)package->appids[package->classes[i].AppIDIndex].AppID,
-             (strlenW(package->appids[package->classes[i].AppIDIndex].AppID)+1)
-             *sizeof(WCHAR));
-
-            register_appid(package,package->classes[i].AppIDIndex,
-                            package->classes[i].Description);
-        }
-
-        if (package->classes[i].IconPath)
-        {
-            static const WCHAR szDefaultIcon[] = 
-                {'D','e','f','a','u','l','t','I','c','o','n',0};
-
-            RegCreateKeyW(hkey2,szDefaultIcon,&hkey3);
-
-            RegSetValueExW(hkey3,NULL,0,REG_SZ,
-                           (LPVOID)package->classes[i].IconPath,
-                           (strlenW(package->classes[i].IconPath)+1) * 
-                           sizeof(WCHAR));
-
-            RegCloseKey(hkey3);
-        }
-
-        if (package->classes[i].DefInprocHandler)
-        {
-            static const WCHAR szInproc[] =
-                {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
-
-            size = (strlenW(package->classes[i].DefInprocHandler) + 1) * 
-                    sizeof(WCHAR);
-            RegCreateKeyW(hkey2,szInproc,&hkey3);
-            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
-                            (LPVOID)package->classes[i].DefInprocHandler, size);
-            RegCloseKey(hkey3);
-        }
-
-        if (package->classes[i].DefInprocHandler32)
-        {
-            static const WCHAR szInproc32[] =
-                {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',
-                 0};
-            size = (strlenW(package->classes[i].DefInprocHandler32) + 1) * 
-                    sizeof(WCHAR);
-
-            RegCreateKeyW(hkey2,szInproc32,&hkey3);
-            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
-                           (LPVOID)package->classes[i].DefInprocHandler32,size);
-            RegCloseKey(hkey3);
-        }
-        
-        RegCloseKey(hkey2);
-
-        /* if there is a FileTypeMask, register the FileType */
-        if (package->classes[i].FileTypeMask)
-        {
-            LPWSTR ptr, ptr2;
-            LPWSTR keyname;
-            INT index = 0;
-            ptr = package->classes[i].FileTypeMask;
-            while (ptr && *ptr)
-            {
-                ptr2 = strchrW(ptr,';');
-                if (ptr2)
-                    *ptr2 = 0;
-                keyname = HeapAlloc(GetProcessHeap(),0,(strlenW(szFileType_fmt)+
-                                        strlenW(package->classes[i].CLSID) + 4)
-                                * sizeof(WCHAR));
-                sprintfW(keyname,szFileType_fmt, package->classes[i].CLSID, 
-                        index);
-
-                RegCreateKeyW(HKEY_CLASSES_ROOT,keyname,&hkey2);
-                RegSetValueExW(hkey2,NULL,0,REG_SZ, (LPVOID)ptr,
-                        strlenW(ptr)*sizeof(WCHAR));
-                RegCloseKey(hkey2);
-                HeapFree(GetProcessHeap(), 0, keyname);
-
-                if (ptr2)
-                    ptr = ptr2+1;
-                else
-                    ptr = NULL;
-
-                index ++;
-            }
-        }
-        
-        uirow = MSI_CreateRecord(1);
-
-        MSI_RecordSetStringW(uirow,1,package->classes[i].CLSID);
-        ui_actiondata(package,szRegisterClassInfo,uirow);
-        msiobj_release(&uirow->hdr);
-    }
-
-    RegCloseKey(hkey);
-    return rc;
-}
-
-static UINT register_progid_base(MSIPACKAGE* package, MSIPROGID* progid,
-                                 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;
-
-    RegCreateKeyW(HKEY_CLASSES_ROOT,progid->ProgID,&hkey);
-
-    if (progid->Description)
-    {
-        RegSetValueExW(hkey,NULL,0,REG_SZ,
-                        (LPVOID)progid->Description, 
-                        (strlenW(progid->Description)+1) *
-                       sizeof(WCHAR));
-    }
-
-    if (progid->ClassIndex >= 0)
-    {   
-        RegCreateKeyW(hkey,szCLSID,&hkey2);
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,
-                        (LPVOID)package->classes[progid->ClassIndex].CLSID, 
-                        (strlenW(package->classes[progid->ClassIndex].CLSID)+1)
-                        * sizeof(WCHAR));
-
-        if (clsid)
-            strcpyW(clsid,package->classes[progid->ClassIndex].CLSID);
-
-        RegCloseKey(hkey2);
-    }
-    else
-    {
-        FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
-    }
-
-    if (progid->IconPath)
-    {
-        RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
-
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)progid->IconPath,
-                           (strlenW(progid->IconPath)+1) * sizeof(WCHAR));
-        RegCloseKey(hkey2);
-    }
-    return ERROR_SUCCESS;
-}
-
-static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid, 
-                LPWSTR clsid)
-{
-    UINT rc = ERROR_SUCCESS; 
-
-    if (progid->ParentIndex < 0)
-        rc = register_progid_base(package, progid, clsid);
-    else
-    {
-        DWORD 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};
-        static const WCHAR szCurVer[] =
-            {'C','u','r','V','e','r',0};
-
-        /* check if already registered */
-        RegCreateKeyExW(HKEY_CLASSES_ROOT, progid->ProgID, 0, NULL, 0,
-                        KEY_ALL_ACCESS, NULL, &hkey, &disp );
-        if (disp == REG_OPENED_EXISTING_KEY)
-        {
-            TRACE("Key already registered\n");
-            RegCloseKey(hkey);
-            return rc;
-        }
-
-        TRACE("Registering Parent %s index %i\n",
-                    debugstr_w(package->progids[progid->ParentIndex].ProgID), 
-                    progid->ParentIndex);
-        rc = register_progid(package,&package->progids[progid->ParentIndex],
-                        clsid);
-
-        /* clsid is same as parent */
-        RegCreateKeyW(hkey,szCLSID,&hkey2);
-        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
-                       sizeof(WCHAR));
-
-        RegCloseKey(hkey2);
-
-
-        if (progid->Description)
-        {
-            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid->Description,
-                           (strlenW(progid->Description)+1) * sizeof(WCHAR));
-        }
-
-        if (progid->IconPath)
-        {
-            RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
-            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)progid->IconPath,
-                           (strlenW(progid->IconPath)+1) * sizeof(WCHAR));
-            RegCloseKey(hkey2);
-        }
-
-        /* write out the current version */
-        if (progid->CurVerIndex >= 0)
-        {
-            RegCreateKeyW(hkey,szCurVer,&hkey2);
-            RegSetValueExW(hkey2,NULL,0,REG_SZ,
-                (LPVOID)package->progids[progid->CurVerIndex].ProgID,
-                (strlenW(package->progids[progid->CurVerIndex].ProgID)+1) * 
-                sizeof(WCHAR));
-            RegCloseKey(hkey2);
-        }
-
-        RegCloseKey(hkey);
-    }
-    return rc;
-}
-
-static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
-{
-    INT i;
-    MSIRECORD *uirow;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    load_classes_and_such(package);
-
-    for (i = 0; i < package->loaded_progids; i++)
-    {
-        WCHAR clsid[0x1000];
-
-        /* check if this progid is to be installed */
-        package->progids[i].InstallMe =  ((package->progids[i].InstallMe) ||
-              (package->progids[i].ClassIndex >= 0 &&
-              package->classes[package->progids[i].ClassIndex].Installed));
-
-        if (!package->progids[i].InstallMe)
-        {
-            TRACE("progid %s not scheduled to be installed\n",
-                             debugstr_w(package->progids[i].ProgID));
-            continue;
-        }
-       
-        TRACE("Registering progid %s index %i\n",
-                        debugstr_w(package->progids[i].ProgID), i);
-
-        register_progid(package,&package->progids[i],clsid);
-
-        uirow = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(uirow,1,package->progids[i].ProgID);
-        ui_actiondata(package,szRegisterProgIdInfo,uirow);
-        msiobj_release(&uirow->hdr);
-    }
-
-    return ERROR_SUCCESS;
-}
-
 static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
 {
     UINT rc;
@@ -5875,291 +4610,6 @@
      * we are currently doing what should be done here in the top level Install
      * however for Adminastrative and uninstalls this step will be needed
      */
-    return ERROR_SUCCESS;
-}
-
-static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, 
-                MSICOMPONENT* component, MSIEXTENSION* extension,
-                MSIVERB* verb, INT* Sequence )
-{
-    LPWSTR keyname;
-    HKEY key;
-    static const WCHAR szShell[] = {'s','h','e','l','l',0};
-    static const WCHAR szCommand[] = {'c','o','m','m','a','n','d',0};
-    static const WCHAR fmt[] = {'\"','%','s','\"',' ','%','s',0};
-    static const WCHAR fmt2[] = {'\"','%','s','\"',0};
-    LPWSTR command;
-    DWORD size;
-    LPWSTR advertise;
-
-    keyname = build_directory_name(4, progid, szShell, verb->Verb, szCommand);
-
-    TRACE("Making Key %s\n",debugstr_w(keyname));
-    RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
-    size = strlenW(component->FullKeypath);
-    if (verb->Argument)
-        size += strlenW(verb->Argument);
-     size += 4;
-
-     command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
-     if (verb->Argument)
-        sprintfW(command, fmt, component->FullKeypath, verb->Argument);
-     else
-        sprintfW(command, fmt2, component->FullKeypath);
-
-     RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)command, (strlenW(command)+1)*
-                     sizeof(WCHAR));
-     HeapFree(GetProcessHeap(),0,command);
-
-     advertise = create_component_advertise_string(package, component, 
-                        package->features[extension->FeatureIndex].Feature);
-
-     size = strlenW(advertise);
-
-     if (verb->Argument)
-        size += strlenW(verb->Argument);
-     size += 4;
-
-     command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
-     memset(command,0,size*sizeof(WCHAR));
-
-     strcpyW(command,advertise);
-     if (verb->Argument)
-     {
-        static const WCHAR szSpace[] = {' ',0};
-         strcatW(command,szSpace);
-         strcatW(command,verb->Argument);
-     }
-
-     RegSetValueExW(key, szCommand, 0, REG_MULTI_SZ, (LPBYTE)command,
-                        (strlenW(command)+2)*sizeof(WCHAR));
-     
-     RegCloseKey(key);
-     HeapFree(GetProcessHeap(),0,keyname);
-     HeapFree(GetProcessHeap(),0,advertise);
-     HeapFree(GetProcessHeap(),0,command);
-
-     if (verb->Command)
-     {
-        keyname = build_directory_name(3, progid, szShell, verb->Verb);
-        RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
-        RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)verb->Command,
-                                    (strlenW(verb->Command)+1) *sizeof(WCHAR));
-        RegCloseKey(key);
-        HeapFree(GetProcessHeap(),0,keyname);
-     }
-
-     if (verb->Sequence != MSI_NULL_INTEGER)
-     {
-        if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
-        {
-            *Sequence = verb->Sequence;
-            keyname = build_directory_name(2, progid, szShell);
-            RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
-            RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)verb->Verb,
-                            (strlenW(verb->Verb)+1) *sizeof(WCHAR));
-            RegCloseKey(key);
-            HeapFree(GetProcessHeap(),0,keyname);
-        }
-    }
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
-{
-    static const WCHAR szContentType[] = 
-        {'C','o','n','t','e','n','t',' ','T','y','p','e',0 };
-    HKEY hkey;
-    INT i;
-    MSIRECORD *uirow;
-    BOOL install_on_demand = TRUE;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    load_classes_and_such(package);
-
-    /* We need to set install_on_demand based on if the shell handles advertised
-     * shortcuts and the like. Because Mike McCormack is working on this i am
-     * going to default to TRUE
-     */
-    
-    for (i = 0; i < package->loaded_extensions; i++)
-    {
-        WCHAR extension[257];
-        INT index,f_index;
-     
-        index = package->extensions[i].ComponentIndex;
-        f_index = package->extensions[i].FeatureIndex;
-
-        if (index < 0)
-            continue;
-
-        /* 
-         * yes. MSDN says that these are based on _Feature_ not on
-         * Component.  So verify the feature is to be installed
-         */
-        if ((!ACTION_VerifyFeatureForAction(package, f_index,
-                                INSTALLSTATE_LOCAL)) &&
-             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
-                             f_index, INSTALLSTATE_ADVERTISED)))
-        {
-            TRACE("Skipping extension  %s reg due to disabled feature %s\n",
-                            debugstr_w(package->extensions[i].Extension),
-                            debugstr_w(package->features[f_index].Feature));
-
-            continue;
-        }
-
-        TRACE("Registering extension %s index %i\n",
-                        debugstr_w(package->extensions[i].Extension), i);
-
-        package->extensions[i].Installed = TRUE;
-
-        /* this is only registered if the extension has at least 1 verb
-         * according to MSDN
-         */
-        if (package->extensions[i].ProgIDIndex >= 0 &&
-                package->extensions[i].VerbCount > 0)
-           mark_progid_for_install(package, package->extensions[i].ProgIDIndex);
-
-        if (package->extensions[i].MIMEIndex >= 0)
-           mark_mime_for_install(package, package->extensions[i].MIMEIndex);
-
-        extension[0] = '.';
-        extension[1] = 0;
-        strcatW(extension,package->extensions[i].Extension);
-
-        RegCreateKeyW(HKEY_CLASSES_ROOT,extension,&hkey);
-
-        if (package->extensions[i].MIMEIndex >= 0)
-        {
-            RegSetValueExW(hkey,szContentType,0,REG_SZ,
-                            (LPVOID)package->mimes[package->extensions[i].
-                                MIMEIndex].ContentType,
-                           (strlenW(package->mimes[package->extensions[i].
-                                    MIMEIndex].ContentType)+1)*sizeof(WCHAR));
-        }
-
-        if (package->extensions[i].ProgIDIndex >= 0 || 
-            package->extensions[i].ProgIDText)
-        {
-            static const WCHAR szSN[] = 
-                {'\\','S','h','e','l','l','N','e','w',0};
-            HKEY hkey2;
-            LPWSTR newkey;
-            LPCWSTR progid;
-            INT v;
-            INT Sequence = MSI_NULL_INTEGER;
-            
-            if (package->extensions[i].ProgIDIndex >= 0)
-                progid = package->progids[package->extensions[i].
-                    ProgIDIndex].ProgID;
-            else
-                progid = package->extensions[i].ProgIDText;
-
-            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid,
-                           (strlenW(progid)+1)*sizeof(WCHAR));
-
-            newkey = HeapAlloc(GetProcessHeap(),0,
-                           (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); 
-
-            strcpyW(newkey,progid);
-            strcatW(newkey,szSN);
-            RegCreateKeyW(hkey,newkey,&hkey2);
-            RegCloseKey(hkey2);
-
-            HeapFree(GetProcessHeap(),0,newkey);
-
-            /* do all the verbs */
-            for (v = 0; v < package->extensions[i].VerbCount; v++)
-                register_verb(package, progid, 
-                              &package->components[index],
-                              &package->extensions[i],
-                              &package->verbs[package->extensions[i].Verbs[v]], 
-                              &Sequence);
-        }
-        
-        RegCloseKey(hkey);
-
-        uirow = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(uirow,1,package->extensions[i].Extension);
-        ui_actiondata(package,szRegisterExtensionInfo,uirow);
-        msiobj_release(&uirow->hdr);
-    }
-
-    return ERROR_SUCCESS;
-}
-
-static UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
-{
-    static const WCHAR szExten[] = 
-        {'E','x','t','e','n','s','i','o','n',0 };
-    HKEY hkey;
-    INT i;
-    MSIRECORD *uirow;
-
-    if (!package)
-        return ERROR_INVALID_HANDLE;
-
-    load_classes_and_such(package);
-
-    for (i = 0; i < package->loaded_mimes; i++)
-    {
-        WCHAR extension[257];
-        LPCWSTR exten;
-        LPCWSTR mime;
-        static const WCHAR fmt[] = 
-            {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\',
-             'C','o','n','t','e','n','t',' ','T','y','p','e','\\', '%','s',0};
-        LPWSTR key;
-
-        /* 
-         * check if the MIME is to be installed. Either as requesed by an
-         * extension or Class
-         */
-        package->mimes[i].InstallMe =  ((package->mimes[i].InstallMe) ||
-              (package->mimes[i].ClassIndex >= 0 &&
-              package->classes[package->mimes[i].ClassIndex].Installed) ||
-              (package->mimes[i].ExtensionIndex >=0 &&
-              package->extensions[package->mimes[i].ExtensionIndex].Installed));
-
-        if (!package->mimes[i].InstallMe)
-        {
-            TRACE("MIME %s not scheduled to be installed\n",
-                             debugstr_w(package->mimes[i].ContentType));
-            continue;
-        }
-        
-        mime = package->mimes[i].ContentType;
-        exten = package->extensions[package->mimes[i].ExtensionIndex].Extension;
-        extension[0] = '.';
-        extension[1] = 0;
-        strcatW(extension,exten);
-
-        key = HeapAlloc(GetProcessHeap(),0,(strlenW(mime)+strlenW(fmt)+1) *
-                                            sizeof(WCHAR));
-        sprintfW(key,fmt,mime);
-        RegCreateKeyW(HKEY_CLASSES_ROOT,key,&hkey);
-        RegSetValueExW(hkey,szExten,0,REG_SZ,(LPVOID)extension,
-                           (strlenW(extension)+1)*sizeof(WCHAR));
-
-        HeapFree(GetProcessHeap(),0,key);
-
-        if (package->mimes[i].CLSID[0])
-        {
-            FIXME("Handle non null for field 3\n");
-        }
-
-        RegCloseKey(hkey);
-
-        uirow = MSI_CreateRecord(2);
-        MSI_RecordSetStringW(uirow,1,package->mimes[i].ContentType);
-        MSI_RecordSetStringW(uirow,2,exten);
-        ui_actiondata(package,szRegisterMIMEInfo,uirow);
-        msiobj_release(&uirow->hdr);
-    }
-
     return ERROR_SUCCESS;
 }
 
Index: dlls/msi/action.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.h,v
retrieving revision 1.17
diff -u -r1.17 action.h
--- dlls/msi/action.h	15 Jun 2005 19:12:42 -0000	1.17
+++ dlls/msi/action.h	16 Jun 2005 12:45:43 -0000
@@ -201,9 +201,14 @@
 UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
 void ACTION_FinishCustomActions( MSIPACKAGE* package);
 UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
-void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
+
+/* actions in other modules */
 UINT ACTION_AppSearch(MSIPACKAGE *package);
 UINT ACTION_FindRelatedProducts(MSIPACKAGE *package);
+UINT ACTION_RegisterClassInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package);
+UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package);
 
 
 /* Helpers */

--- /dev//null	2005-03-17 08:20:53.000000000 -0600
+++ dlls/msi/classes.c	2005-06-16 07:35:12.000000000 -0500
@@ -0,0 +1,1603 @@
+/*
+ * Implementation of the Microsoft Installer (msi.dll)
+ *
+ * Copyright 2005 Aric Stewart for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* actions handled in this module
+ * RegisterClassInfo
+ * RegisterProgIdInfo
+ * RegisterExtensionInfo
+ * RegisterMIMEInfo
+ * UnRegisterClassInfo (TODO)
+ * UnRegisterProgIdInfo (TODO)
+ * UnRegisterExtensionInfo (TODO)
+ * UnRegisterMIMEInfo (TODO)
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "wine/debug.h"
+#include "msipriv.h"
+#include "winuser.h"
+#include "wine/unicode.h"
+#include "action.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
+
+
+extern const WCHAR szRegisterClassInfo[];
+extern const WCHAR szRegisterProgIdInfo[];
+extern WCHAR szRegisterExtensionInfo[];
+extern const WCHAR szRegisterMIMEInfo[];
+
+extern const WCHAR szUnregisterClassInfo[];
+extern const WCHAR szUnregisterExtensionInfo[];
+extern const WCHAR szUnregisterMIMEInfo[];
+extern const WCHAR szUnregisterProgIdInfo[];
+
+static INT load_appid(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_appids;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_appids++;
+    if (package->loaded_appids == 1)
+        package->appids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIAPPID));
+    else
+        package->appids = HeapReAlloc(GetProcessHeap(),0,
+            package->appids, package->loaded_appids * sizeof(MSIAPPID));
+
+    memset(&package->appids[index],0,sizeof(MSIAPPID));
+    
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 1, package->appids[index].AppID, &sz);
+    TRACE("loading appid %s\n",debugstr_w(package->appids[index].AppID));
+
+    buffer = MSI_RecordGetString(row,2);
+    deformat_string(package,buffer,&package->appids[index].RemoteServerName);
+
+    package->appids[index].LocalServer = load_dynamic_stringW(row,3);
+    package->appids[index].ServiceParameters = load_dynamic_stringW(row,4);
+    package->appids[index].DllSurrogate = load_dynamic_stringW(row,5);
+
+    package->appids[index].ActivateAtStorage = !MSI_RecordIsNull(row,6);
+    package->appids[index].RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
+    
+    return index;
+}
+
+static INT load_given_appid(MSIPACKAGE *package, LPCWSTR appid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','A','p','p','I','d','`',' ','W','H','E','R','E',' ',
+         '`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0};
+
+    if (!appid)
+        return -1;
+
+    /* check for appids already loaded */
+    for (i = 0; i < package->loaded_appids; i++)
+        if (strcmpiW(package->appids[i].AppID,appid)==0)
+        {
+            TRACE("found appid %s at index %i\n",debugstr_w(appid),i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, appid);
+    if (!row)
+        return -1;
+
+    rc = load_appid(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
+static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid);
+
+static INT load_progid(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_progids;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_progids++;
+    if (package->loaded_progids == 1)
+        package->progids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIPROGID));
+    else
+        package->progids = HeapReAlloc(GetProcessHeap(),0,
+            package->progids , package->loaded_progids * sizeof(MSIPROGID));
+
+    memset(&package->progids[index],0,sizeof(MSIPROGID));
+
+    package->progids[index].ProgID = load_dynamic_stringW(row,1);
+    TRACE("loading progid %s\n",debugstr_w(package->progids[index].ProgID));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->progids[index].ParentIndex = load_given_progid(package,buffer);
+    if (package->progids[index].ParentIndex < 0 && buffer)
+        FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
+
+    buffer = MSI_RecordGetString(row,3);
+    package->progids[index].ClassIndex = load_given_class(package,buffer);
+    if (package->progids[index].ClassIndex< 0 && buffer)
+        FIXME("Unknown class %s\n",debugstr_w(buffer));
+
+    package->progids[index].Description = load_dynamic_stringW(row,4);
+
+    if (!MSI_RecordIsNull(row,6))
+    {
+        INT icon_index = MSI_RecordGetInteger(row,6); 
+        LPWSTR FileName = load_dynamic_stringW(row,5);
+        LPWSTR FilePath;
+        static const WCHAR fmt[] = {'%','s',',','%','i',0};
+
+        build_icon_path(package,FileName,&FilePath);
+       
+        package->progids[index].IconPath = 
+                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+10)*
+                                sizeof(WCHAR));
+
+        sprintfW(package->progids[index].IconPath,fmt,FilePath,icon_index);
+
+        HeapFree(GetProcessHeap(),0,FilePath);
+        HeapFree(GetProcessHeap(),0,FileName);
+    }
+    else
+    {
+        buffer = MSI_RecordGetString(row,5);
+        if (buffer)
+            build_icon_path(package,buffer,&(package->progids[index].IconPath));
+    }
+
+    package->progids[index].CurVerIndex = -1;
+    package->progids[index].VersionIndIndex = -1;
+
+    /* if we have a parent then we may be that parents CurVer */
+    if (package->progids[index].ParentIndex >= 0 && 
+        package->progids[index].ParentIndex != index)
+    {
+        int pindex = package->progids[index].ParentIndex;
+        while (package->progids[pindex].ParentIndex>= 0 && 
+               package->progids[pindex].ParentIndex != pindex)
+            pindex = package->progids[pindex].ParentIndex;
+
+        FIXME("BAD BAD need to determing if we are really the CurVer\n");
+
+        package->progids[index].CurVerIndex = pindex;
+        package->progids[pindex].VersionIndIndex = index;
+    }
+    
+    return index;
+}
+
+static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ',
+         '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
+
+    if (!progid)
+        return -1;
+
+    /* check for progids already loaded */
+    for (i = 0; i < package->loaded_progids; i++)
+        if (strcmpiW(package->progids[i].ProgID,progid)==0)
+        {
+            TRACE("found progid %s at index %i\n",debugstr_w(progid), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, progid);
+    if(!row)
+        return -1;
+
+    rc = load_progid(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_class(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_classes;
+    DWORD sz,i;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_classes++;
+    if (package->loaded_classes== 1)
+        package->classes = HeapAlloc(GetProcessHeap(),0,sizeof(MSICLASS));
+    else
+        package->classes = HeapReAlloc(GetProcessHeap(),0,
+            package->classes, package->loaded_classes * sizeof(MSICLASS));
+
+    memset(&package->classes[index],0,sizeof(MSICLASS));
+
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 1, package->classes[index].CLSID, &sz);
+    TRACE("loading class %s\n",debugstr_w(package->classes[index].CLSID));
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row, 2, package->classes[index].Context, &sz);
+    buffer = MSI_RecordGetString(row,3);
+    package->classes[index].ComponentIndex = get_loaded_component(package, 
+                    buffer);
+
+    package->classes[index].ProgIDText = load_dynamic_stringW(row,4);
+    package->classes[index].ProgIDIndex = 
+                load_given_progid(package, package->classes[index].ProgIDText);
+
+    package->classes[index].Description = load_dynamic_stringW(row,5);
+
+    buffer = MSI_RecordGetString(row,6);
+    if (buffer)
+        package->classes[index].AppIDIndex = 
+                load_given_appid(package, buffer);
+    else
+        package->classes[index].AppIDIndex = -1;
+
+    package->classes[index].FileTypeMask = load_dynamic_stringW(row,7);
+
+    if (!MSI_RecordIsNull(row,9))
+    {
+
+        INT icon_index = MSI_RecordGetInteger(row,9); 
+        LPWSTR FileName = load_dynamic_stringW(row,8);
+        LPWSTR FilePath;
+        static const WCHAR fmt[] = {'%','s',',','%','i',0};
+
+        build_icon_path(package,FileName,&FilePath);
+       
+        package->classes[index].IconPath = 
+                HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+5)*
+                                sizeof(WCHAR));
+
+        sprintfW(package->classes[index].IconPath,fmt,FilePath,icon_index);
+
+        HeapFree(GetProcessHeap(),0,FilePath);
+        HeapFree(GetProcessHeap(),0,FileName);
+    }
+    else
+    {
+        buffer = MSI_RecordGetString(row,8);
+        if (buffer)
+            build_icon_path(package,buffer,&(package->classes[index].IconPath));
+    }
+
+    if (!MSI_RecordIsNull(row,10))
+    {
+        i = MSI_RecordGetInteger(row,10);
+        if (i != MSI_NULL_INTEGER && i > 0 &&  i < 4)
+        {
+            static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
+            static const WCHAR ole32[] = {'o','l','e','3','2','.','d','l','l',0};
+
+            switch(i)
+            {
+                case 1:
+                    package->classes[index].DefInprocHandler = strdupW(ole2);
+                    break;
+                case 2:
+                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
+                    break;
+                case 3:
+                    package->classes[index].DefInprocHandler = strdupW(ole2);
+                    package->classes[index].DefInprocHandler32 = strdupW(ole32);
+                    break;
+            }
+        }
+        else
+        {
+            package->classes[index].DefInprocHandler32 = load_dynamic_stringW(
+                            row, 10);
+            reduce_to_longfilename(package->classes[index].DefInprocHandler32);
+        }
+    }
+    buffer = MSI_RecordGetString(row,11);
+    deformat_string(package,buffer,&package->classes[index].Argument);
+
+    buffer = MSI_RecordGetString(row,12);
+    package->classes[index].FeatureIndex = get_loaded_feature(package,buffer);
+
+    package->classes[index].Attributes = MSI_RecordGetInteger(row,13);
+    
+    return index;
+}
+
+/*
+ * the Class table has 3 primary keys. Generally it is only 
+ * referenced through the first CLSID key. However when loading
+ * all of the classes we need to make sure we do not ignore rows
+ * with other Context and ComponentIndexs 
+ */
+static INT load_given_class(MSIPACKAGE *package, LPCWSTR classid)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','C','l','a','s','s','`',' ','W','H','E','R','E',' ',
+         '`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0};
+
+
+    if (!classid)
+        return -1;
+    
+    /* check for classes already loaded */
+    for (i = 0; i < package->loaded_classes; i++)
+        if (strcmpiW(package->classes[i].CLSID,classid)==0)
+        {
+            TRACE("found class %s at index %i\n",debugstr_w(classid), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, classid);
+    if (!row)
+        return -1;
+
+    rc = load_class(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension);
+
+static INT load_mime(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_mimes;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_mimes++;
+    if (package->loaded_mimes== 1)
+        package->mimes= HeapAlloc(GetProcessHeap(),0,sizeof(MSIMIME));
+    else
+        package->mimes= HeapReAlloc(GetProcessHeap(),0,
+            package->mimes, package->loaded_mimes* 
+            sizeof(MSIMIME));
+
+    memset(&package->mimes[index],0,sizeof(MSIMIME));
+
+    package->mimes[index].ContentType = load_dynamic_stringW(row,1); 
+    TRACE("loading mime %s\n",debugstr_w(package->mimes[index].ContentType));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->mimes[index].ExtensionIndex = load_given_extension(package,
+                    buffer);
+
+    sz = IDENTIFIER_SIZE;
+    MSI_RecordGetStringW(row,3,package->mimes[index].CLSID,&sz);
+    package->mimes[index].ClassIndex= load_given_class(package,
+                    package->mimes[index].CLSID);
+    
+    return index;
+}
+
+static INT load_given_mime(MSIPACKAGE *package, LPCWSTR mime)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','M','I','M','E','`',' ','W','H','E','R','E',' ',
+         '`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ',
+         '\'','%','s','\'',0};
+
+    if (!mime)
+        return -1;
+    
+    /* check for mime already loaded */
+    for (i = 0; i < package->loaded_mimes; i++)
+        if (strcmpiW(package->mimes[i].ContentType,mime)==0)
+        {
+            TRACE("found mime %s at index %i\n",debugstr_w(mime), i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, mime);
+    if (!row)
+        return -1;
+
+    rc = load_mime(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static INT load_extension(MSIPACKAGE* package, MSIRECORD *row)
+{
+    DWORD index = package->loaded_extensions;
+    DWORD sz;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_extensions++;
+    if (package->loaded_extensions == 1)
+        package->extensions = HeapAlloc(GetProcessHeap(),0,sizeof(MSIEXTENSION));
+    else
+        package->extensions = HeapReAlloc(GetProcessHeap(),0,
+            package->extensions, package->loaded_extensions* 
+            sizeof(MSIEXTENSION));
+
+    memset(&package->extensions[index],0,sizeof(MSIEXTENSION));
+
+    sz = 256;
+    MSI_RecordGetStringW(row,1,package->extensions[index].Extension,&sz);
+    TRACE("loading extension %s\n",
+                    debugstr_w(package->extensions[index].Extension));
+
+    buffer = MSI_RecordGetString(row,2);
+    package->extensions[index].ComponentIndex = 
+            get_loaded_component(package,buffer);
+
+    package->extensions[index].ProgIDText = load_dynamic_stringW(row,3);
+    package->extensions[index].ProgIDIndex = load_given_progid(package,
+                    package->extensions[index].ProgIDText);
+
+    buffer = MSI_RecordGetString(row,4);
+    package->extensions[index].MIMEIndex = load_given_mime(package,buffer);
+
+    buffer = MSI_RecordGetString(row,5);
+    package->extensions[index].FeatureIndex = 
+            get_loaded_feature(package,buffer);
+
+    return index;
+}
+
+/*
+ * While the extension table has 2 primary keys, this function is only looking
+ * at the Extension key which is what is referenced as a forign key 
+ */
+static INT load_given_extension(MSIPACKAGE *package, LPCWSTR extension)
+{
+    INT rc;
+    MSIRECORD *row;
+    INT i;
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',' ',
+         'W','H','E','R','E',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',' ','=',' ',
+         '\'','%','s','\'',0};
+
+    if (!extension)
+        return -1;
+
+    /* check for extensions already loaded */
+    for (i = 0; i < package->loaded_extensions; i++)
+        if (strcmpiW(package->extensions[i].Extension,extension)==0)
+        {
+            TRACE("extension %s already loaded at %i\n",debugstr_w(extension),
+                            i);
+            return i;
+        }
+    
+    row = MSI_QueryGetRecord(package->db, ExecSeqQuery, extension);
+    if (!row)
+        return -1;
+
+    rc = load_extension(package, row);
+    msiobj_release(&row->hdr);
+
+    return rc;
+}
+
+static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    DWORD index = package->loaded_verbs;
+    LPCWSTR buffer;
+
+    /* fill in the data */
+
+    package->loaded_verbs++;
+    if (package->loaded_verbs == 1)
+        package->verbs = HeapAlloc(GetProcessHeap(),0,sizeof(MSIVERB));
+    else
+        package->verbs = HeapReAlloc(GetProcessHeap(),0,
+            package->verbs , package->loaded_verbs * sizeof(MSIVERB));
+
+    memset(&package->verbs[index],0,sizeof(MSIVERB));
+
+    buffer = MSI_RecordGetString(row,1);
+    package->verbs[index].ExtensionIndex = load_given_extension(package,buffer);
+    if (package->verbs[index].ExtensionIndex < 0 && buffer)
+        ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
+
+    package->verbs[index].Verb = load_dynamic_stringW(row,2);
+    TRACE("loading verb %s\n",debugstr_w(package->verbs[index].Verb));
+    package->verbs[index].Sequence = MSI_RecordGetInteger(row,3);
+
+    buffer = MSI_RecordGetString(row,4);
+    deformat_string(package,buffer,&package->verbs[index].Command);
+
+    buffer = MSI_RecordGetString(row,5);
+    deformat_string(package,buffer,&package->verbs[index].Argument);
+
+    /* assosiate the verb with the correct extension */
+    if (package->verbs[index].ExtensionIndex >= 0)
+    {
+        MSIEXTENSION* extension = &package->extensions[package->verbs[index].
+                ExtensionIndex];
+        int count = extension->VerbCount;
+
+        if (count >= 99)
+            FIXME("Exceeding max verb count! Increase that limit!!!\n");
+        else
+        {
+            extension->VerbCount++;
+            extension->Verbs[count] = index;
+        }
+    }
+    
+    return ERROR_SUCCESS;
+}
+
+static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR clsid;
+    LPCWSTR context;
+    LPCWSTR buffer;
+    INT    component_index;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+    INT i;
+    BOOL match = FALSE;
+
+    clsid = MSI_RecordGetString(rec,1);
+    context = MSI_RecordGetString(rec,2);
+    buffer = MSI_RecordGetString(rec,3);
+    component_index = get_loaded_component(package,buffer);
+
+    for (i = 0; i < package->loaded_classes; i++)
+    {
+        if (strcmpiW(clsid,package->classes[i].CLSID))
+            continue;
+        if (strcmpW(context,package->classes[i].Context))
+            continue;
+        if (component_index == package->classes[i].ComponentIndex)
+        {
+            match = TRUE;
+            break;
+        }
+    }
+    
+    if (!match)
+        load_class(package, rec);
+
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_classes(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
+         '`','C','l','a','s','s','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    LPCWSTR extension;
+    INT    component_index;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+    BOOL match = FALSE;
+    INT i;
+
+    extension = MSI_RecordGetString(rec,1);
+    buffer = MSI_RecordGetString(rec,2);
+    component_index = get_loaded_component(package,buffer);
+
+    for (i = 0; i < package->loaded_extensions; i++)
+    {
+        if (strcmpiW(extension,package->extensions[i].Extension))
+            continue;
+        if (component_index == package->extensions[i].ComponentIndex)
+        {
+            match = TRUE;
+            break;
+        }
+    }
+
+    if (!match)
+        load_extension(package, rec);
+
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_extensions(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','E','x','t','e','n','s','i','o','n','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+
+    buffer = MSI_RecordGetString(rec,1);
+    load_given_progid(package,buffer);
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_progids(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ',
+         'F','R','O','M',' ', '`','P','r','o','g','I','d','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
+    msiobj_release(&view->hdr);
+}
+
+static VOID load_all_verbs(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+         '`','V','e','r','b','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
+    msiobj_release(&view->hdr);
+}
+
+static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
+{
+    LPCWSTR buffer;
+    MSIPACKAGE* package =(MSIPACKAGE*)param;
+
+    buffer = MSI_RecordGetString(rec,1);
+    load_given_mime(package,buffer);
+    return ERROR_SUCCESS;
+}
+
+static VOID load_all_mimes(MSIPACKAGE *package)
+{
+    UINT rc = ERROR_SUCCESS;
+    MSIQUERY *view;
+
+    static const WCHAR ExecSeqQuery[] =
+        {'S','E','L','E','C','T',' ',
+         '`','C','o','n','t','e','n','t','T','y','p','e','`',
+         ' ','F','R','O','M',' ',
+         '`','M','I','M','E','`',0};
+
+    rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
+    if (rc != ERROR_SUCCESS)
+        return;
+
+    rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
+    msiobj_release(&view->hdr);
+}
+
+static void load_classes_and_such(MSIPACKAGE *package)
+{
+    TRACE("Loading all the class info and related tables\n");
+
+    /* check if already loaded */
+    if (package->classes || package->extensions || package->progids || 
+        package->verbs || package->mimes)
+        return;
+
+    load_all_classes(package);
+    load_all_extensions(package);
+    load_all_progids(package);
+    /* these loads must come after the other loads */
+    load_all_verbs(package);
+    load_all_mimes(package);
+}
+
+static void mark_progid_for_install(MSIPACKAGE* package, INT index)
+{
+    MSIPROGID* progid;
+    int i;
+
+    if (index < 0 || index >= package->loaded_progids)
+        return;
+
+    progid = &package->progids[index];
+
+    if (progid->InstallMe == TRUE)
+        return;
+
+    progid->InstallMe = TRUE;
+
+    /* all children if this is a parent also install */
+   for (i = 0; i < package->loaded_progids; i++)
+        if (package->progids[i].ParentIndex == index)
+            mark_progid_for_install(package,i);
+}
+
+static void mark_mime_for_install(MSIPACKAGE* package, INT index)
+{
+    MSIMIME* mime;
+
+    if (index < 0 || index >= package->loaded_mimes)
+        return;
+
+    mime = &package->mimes[index];
+
+    if (mime->InstallMe == TRUE)
+        return;
+
+    mime->InstallMe = TRUE;
+}
+
+static UINT register_appid(MSIPACKAGE *package, int appidIndex, LPCWSTR app )
+{
+    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
+    HKEY hkey2,hkey3;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
+    RegCreateKeyW(hkey2,package->appids[appidIndex].AppID,&hkey3);
+    RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)app,
+                   (strlenW(app)+1)*sizeof(WCHAR));
+
+    if (package->appids[appidIndex].RemoteServerName)
+    {
+        UINT size; 
+        static const WCHAR szRemoteServerName[] =
+             {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',
+              0};
+
+        size = (strlenW(package->appids[appidIndex].RemoteServerName)+1) * 
+                sizeof(WCHAR);
+
+        RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].RemoteServerName,
+                        size);
+    }
+
+    if (package->appids[appidIndex].LocalServer)
+    {
+        static const WCHAR szLocalService[] =
+             {'L','o','c','a','l','S','e','r','v','i','c','e',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].LocalServer)+1) * 
+                sizeof(WCHAR);
+
+        RegSetValueExW(hkey3,szLocalService,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].LocalServer,size);
+    }
+
+    if (package->appids[appidIndex].ServiceParameters)
+    {
+        static const WCHAR szService[] =
+             {'S','e','r','v','i','c','e',
+              'P','a','r','a','m','e','t','e','r','s',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].ServiceParameters)+1) * 
+                sizeof(WCHAR);
+        RegSetValueExW(hkey3,szService,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].ServiceParameters,
+                        size);
+    }
+
+    if (package->appids[appidIndex].DllSurrogate)
+    {
+        static const WCHAR szDLL[] =
+             {'D','l','l','S','u','r','r','o','g','a','t','e',0};
+        UINT size;
+        size = (strlenW(package->appids[appidIndex].DllSurrogate)+1) * 
+                sizeof(WCHAR);
+        RegSetValueExW(hkey3,szDLL,0,REG_SZ,
+                        (LPVOID)package->appids[appidIndex].DllSurrogate,size);
+    }
+
+    if (package->appids[appidIndex].ActivateAtStorage)
+    {
+        static const WCHAR szActivate[] =
+             {'A','c','t','i','v','a','t','e','A','s',
+              'S','t','o','r','a','g','e',0};
+        static const WCHAR szY[] = {'Y',0};
+
+        RegSetValueExW(hkey3,szActivate,0,REG_SZ,(LPVOID)szY,4);
+    }
+
+    if (package->appids[appidIndex].RunAsInteractiveUser)
+    {
+        static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
+        static const WCHAR szUser[] = 
+             {'I','n','t','e','r','a','c','t','i','v','e',' ',
+              'U','s','e','r',0};
+
+        RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,sizeof(szUser));
+    }
+
+    RegCloseKey(hkey3);
+    RegCloseKey(hkey2);
+    return ERROR_SUCCESS;
+}
+
+UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
+{
+    /* 
+     * Again I am assuming the words, "Whose key file represents" when referring
+     * to a Component as to meaning that Components KeyPath file
+     */
+    
+    UINT rc;
+    MSIRECORD *uirow;
+    static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
+    static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
+    static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
+    static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
+    static const WCHAR szSpace[] = {' ',0};
+    static const WCHAR szInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+    static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
+    HKEY hkey,hkey2,hkey3;
+    BOOL install_on_demand = FALSE;
+    int i;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    load_classes_and_such(package);
+    rc = RegCreateKeyW(HKEY_CLASSES_ROOT,szCLSID,&hkey);
+    if (rc != ERROR_SUCCESS)
+        return ERROR_FUNCTION_FAILED;
+
+    /* install_on_demand should be set if OLE supports install on demand OLE
+     * servers. For now i am defaulting to FALSE because i do not know how to
+     * check, and i am told our builtin OLE does not support it
+     */
+    
+    for (i = 0; i < package->loaded_classes; i++)
+    {
+        INT index,f_index;
+        DWORD size, sz;
+        LPWSTR argument;
+
+        if (package->classes[i].ComponentIndex < 0)
+        {
+            continue;
+        }
+
+        index = package->classes[i].ComponentIndex;
+        f_index = package->classes[i].FeatureIndex;
+
+        /* 
+         * yes. MSDN says that these are based on _Feature_ not on
+         * Component.  So verify the feature is to be installed
+         */
+        if ((!ACTION_VerifyFeatureForAction(package, f_index,
+                                INSTALLSTATE_LOCAL)) &&
+             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
+                             f_index, INSTALLSTATE_ADVERTISED)))
+        {
+            TRACE("Skipping class %s reg due to disabled feature %s\n", 
+                            debugstr_w(package->classes[i].CLSID), 
+                            debugstr_w(package->features[f_index].Feature));
+
+            continue;
+        }
+
+        TRACE("Registering index %i  class %s\n",i,
+                        debugstr_w(package->classes[i].CLSID));
+
+        package->classes[i].Installed = TRUE;
+        if (package->classes[i].ProgIDIndex >= 0)
+            mark_progid_for_install(package, package->classes[i].ProgIDIndex);
+
+        RegCreateKeyW(hkey,package->classes[i].CLSID,&hkey2);
+
+        if (package->classes[i].Description)
+            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)package->classes[i].
+                            Description, (strlenW(package->classes[i].
+                                     Description)+1)*sizeof(WCHAR));
+
+        RegCreateKeyW(hkey2,package->classes[i].Context,&hkey3);
+        index = get_loaded_file(package,package->components[index].KeyPath);
+
+
+        /* the context server is a short path name 
+         * except for if it is InprocServer32... 
+         */
+        if (strcmpiW(package->classes[i].Context,szInprocServer32)!=0)
+        {
+            sz = 0;
+            sz = GetShortPathNameW(package->files[index].TargetPath, NULL, 0);
+            if (sz == 0)
+            {
+                ERR("Unable to find short path for CLSID COM Server\n");
+                argument = NULL;
+            }
+            else
+            {
+                size = sz * sizeof(WCHAR);
+
+                if (package->classes[i].Argument)
+                {
+                    size += strlenW(package->classes[i].Argument) * 
+                            sizeof(WCHAR);
+                    size += sizeof(WCHAR);
+                }
+
+                argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
+                GetShortPathNameW(package->files[index].TargetPath, argument, 
+                                sz);
+
+                if (package->classes[i].Argument)
+                {
+                    strcatW(argument,szSpace);
+                    strcatW(argument,package->classes[i].Argument);
+                }
+            }
+        }
+        else
+        {
+            size = lstrlenW(package->files[index].TargetPath) * sizeof(WCHAR);
+
+            if (package->classes[i].Argument)
+            {
+                size += strlenW(package->classes[i].Argument) * sizeof(WCHAR);
+                size += sizeof(WCHAR);
+            }
+
+            argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
+            strcpyW(argument, package->files[index].TargetPath);
+
+            if (package->classes[i].Argument)
+            {
+                strcatW(argument,szSpace);
+                strcatW(argument,package->classes[i].Argument);
+            }
+        }
+
+        if (argument)
+        {
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
+            HeapFree(GetProcessHeap(),0,argument);
+        }
+
+        RegCloseKey(hkey3);
+
+        if (package->classes[i].ProgIDIndex >= 0 || 
+            package->classes[i].ProgIDText)
+        {
+            LPCWSTR progid;
+
+            if (package->classes[i].ProgIDIndex >= 0)
+                progid = package->progids[
+                        package->classes[i].ProgIDIndex].ProgID;
+            else
+                progid = package->classes[i].ProgIDText;
+
+            RegCreateKeyW(hkey2,szProgID,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)progid,
+                            (strlenW(progid)+1) *sizeof(WCHAR));
+            RegCloseKey(hkey3);
+
+            if (package->classes[i].ProgIDIndex >= 0 &&
+                package->progids[package->classes[i].ProgIDIndex].
+                                VersionIndIndex >= 0)
+            {
+                LPWSTR viprogid = strdupW(package->progids[package->progids[
+                        package->classes[i].ProgIDIndex].VersionIndIndex].
+                        ProgID);
+                RegCreateKeyW(hkey2,szVIProgID,&hkey3);
+                RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)viprogid,
+                            (strlenW(viprogid)+1) *sizeof(WCHAR));
+                RegCloseKey(hkey3);
+                HeapFree(GetProcessHeap(), 0, viprogid);
+            }
+        }
+
+        if (package->classes[i].AppIDIndex >= 0)
+        { 
+            RegSetValueExW(hkey2,szAppID,0,REG_SZ,
+             (LPVOID)package->appids[package->classes[i].AppIDIndex].AppID,
+             (strlenW(package->appids[package->classes[i].AppIDIndex].AppID)+1)
+             *sizeof(WCHAR));
+
+            register_appid(package,package->classes[i].AppIDIndex,
+                            package->classes[i].Description);
+        }
+
+        if (package->classes[i].IconPath)
+        {
+            static const WCHAR szDefaultIcon[] = 
+                {'D','e','f','a','u','l','t','I','c','o','n',0};
+
+            RegCreateKeyW(hkey2,szDefaultIcon,&hkey3);
+
+            RegSetValueExW(hkey3,NULL,0,REG_SZ,
+                           (LPVOID)package->classes[i].IconPath,
+                           (strlenW(package->classes[i].IconPath)+1) * 
+                           sizeof(WCHAR));
+
+            RegCloseKey(hkey3);
+        }
+
+        if (package->classes[i].DefInprocHandler)
+        {
+            static const WCHAR szInproc[] =
+                {'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
+
+            size = (strlenW(package->classes[i].DefInprocHandler) + 1) * 
+                    sizeof(WCHAR);
+            RegCreateKeyW(hkey2,szInproc,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
+                            (LPVOID)package->classes[i].DefInprocHandler, size);
+            RegCloseKey(hkey3);
+        }
+
+        if (package->classes[i].DefInprocHandler32)
+        {
+            static const WCHAR szInproc32[] =
+                {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',
+                 0};
+            size = (strlenW(package->classes[i].DefInprocHandler32) + 1) * 
+                    sizeof(WCHAR);
+
+            RegCreateKeyW(hkey2,szInproc32,&hkey3);
+            RegSetValueExW(hkey3,NULL,0,REG_SZ, 
+                           (LPVOID)package->classes[i].DefInprocHandler32,size);
+            RegCloseKey(hkey3);
+        }
+        
+        RegCloseKey(hkey2);
+
+        /* if there is a FileTypeMask, register the FileType */
+        if (package->classes[i].FileTypeMask)
+        {
+            LPWSTR ptr, ptr2;
+            LPWSTR keyname;
+            INT index = 0;
+            ptr = package->classes[i].FileTypeMask;
+            while (ptr && *ptr)
+            {
+                ptr2 = strchrW(ptr,';');
+                if (ptr2)
+                    *ptr2 = 0;
+                keyname = HeapAlloc(GetProcessHeap(),0,(strlenW(szFileType_fmt)+
+                                        strlenW(package->classes[i].CLSID) + 4)
+                                * sizeof(WCHAR));
+                sprintfW(keyname,szFileType_fmt, package->classes[i].CLSID, 
+                        index);
+
+                RegCreateKeyW(HKEY_CLASSES_ROOT,keyname,&hkey2);
+                RegSetValueExW(hkey2,NULL,0,REG_SZ, (LPVOID)ptr,
+                        strlenW(ptr)*sizeof(WCHAR));
+                RegCloseKey(hkey2);
+                HeapFree(GetProcessHeap(), 0, keyname);
+
+                if (ptr2)
+                    ptr = ptr2+1;
+                else
+                    ptr = NULL;
+
+                index ++;
+            }
+        }
+        
+        uirow = MSI_CreateRecord(1);
+
+        MSI_RecordSetStringW(uirow,1,package->classes[i].CLSID);
+        ui_actiondata(package,szRegisterClassInfo,uirow);
+        msiobj_release(&uirow->hdr);
+    }
+
+    RegCloseKey(hkey);
+    return rc;
+}
+
+static UINT register_progid_base(MSIPACKAGE* package, MSIPROGID* progid,
+                                 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;
+
+    RegCreateKeyW(HKEY_CLASSES_ROOT,progid->ProgID,&hkey);
+
+    if (progid->Description)
+    {
+        RegSetValueExW(hkey,NULL,0,REG_SZ,
+                        (LPVOID)progid->Description, 
+                        (strlenW(progid->Description)+1) *
+                       sizeof(WCHAR));
+    }
+
+    if (progid->ClassIndex >= 0)
+    {   
+        RegCreateKeyW(hkey,szCLSID,&hkey2);
+        RegSetValueExW(hkey2,NULL,0,REG_SZ,
+                        (LPVOID)package->classes[progid->ClassIndex].CLSID, 
+                        (strlenW(package->classes[progid->ClassIndex].CLSID)+1)
+                        * sizeof(WCHAR));
+
+        if (clsid)
+            strcpyW(clsid,package->classes[progid->ClassIndex].CLSID);
+
+        RegCloseKey(hkey2);
+    }
+    else
+    {
+        FIXME("UNHANDLED case, Parent progid but classid is NULL\n");
+    }
+
+    if (progid->IconPath)
+    {
+        RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
+
+        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)progid->IconPath,
+                           (strlenW(progid->IconPath)+1) * sizeof(WCHAR));
+        RegCloseKey(hkey2);
+    }
+    return ERROR_SUCCESS;
+}
+
+static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid, 
+                LPWSTR clsid)
+{
+    UINT rc = ERROR_SUCCESS; 
+
+    if (progid->ParentIndex < 0)
+        rc = register_progid_base(package, progid, clsid);
+    else
+    {
+        DWORD 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};
+        static const WCHAR szCurVer[] =
+            {'C','u','r','V','e','r',0};
+
+        /* check if already registered */
+        RegCreateKeyExW(HKEY_CLASSES_ROOT, progid->ProgID, 0, NULL, 0,
+                        KEY_ALL_ACCESS, NULL, &hkey, &disp );
+        if (disp == REG_OPENED_EXISTING_KEY)
+        {
+            TRACE("Key already registered\n");
+            RegCloseKey(hkey);
+            return rc;
+        }
+
+        TRACE("Registering Parent %s index %i\n",
+                    debugstr_w(package->progids[progid->ParentIndex].ProgID), 
+                    progid->ParentIndex);
+        rc = register_progid(package,&package->progids[progid->ParentIndex],
+                        clsid);
+
+        /* clsid is same as parent */
+        RegCreateKeyW(hkey,szCLSID,&hkey2);
+        RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)clsid, (strlenW(clsid)+1) *
+                       sizeof(WCHAR));
+
+        RegCloseKey(hkey2);
+
+
+        if (progid->Description)
+        {
+            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid->Description,
+                           (strlenW(progid->Description)+1) * sizeof(WCHAR));
+        }
+
+        if (progid->IconPath)
+        {
+            RegCreateKeyW(hkey,szDefaultIcon,&hkey2);
+            RegSetValueExW(hkey2,NULL,0,REG_SZ,(LPVOID)progid->IconPath,
+                           (strlenW(progid->IconPath)+1) * sizeof(WCHAR));
+            RegCloseKey(hkey2);
+        }
+
+        /* write out the current version */
+        if (progid->CurVerIndex >= 0)
+        {
+            RegCreateKeyW(hkey,szCurVer,&hkey2);
+            RegSetValueExW(hkey2,NULL,0,REG_SZ,
+                (LPVOID)package->progids[progid->CurVerIndex].ProgID,
+                (strlenW(package->progids[progid->CurVerIndex].ProgID)+1) * 
+                sizeof(WCHAR));
+            RegCloseKey(hkey2);
+        }
+
+        RegCloseKey(hkey);
+    }
+    return rc;
+}
+
+UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
+{
+    INT i;
+    MSIRECORD *uirow;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    load_classes_and_such(package);
+
+    for (i = 0; i < package->loaded_progids; i++)
+    {
+        WCHAR clsid[0x1000];
+
+        /* check if this progid is to be installed */
+        package->progids[i].InstallMe =  ((package->progids[i].InstallMe) ||
+              (package->progids[i].ClassIndex >= 0 &&
+              package->classes[package->progids[i].ClassIndex].Installed));
+
+        if (!package->progids[i].InstallMe)
+        {
+            TRACE("progid %s not scheduled to be installed\n",
+                             debugstr_w(package->progids[i].ProgID));
+            continue;
+        }
+       
+        TRACE("Registering progid %s index %i\n",
+                        debugstr_w(package->progids[i].ProgID), i);
+
+        register_progid(package,&package->progids[i],clsid);
+
+        uirow = MSI_CreateRecord(1);
+        MSI_RecordSetStringW(uirow,1,package->progids[i].ProgID);
+        ui_actiondata(package,szRegisterProgIdInfo,uirow);
+        msiobj_release(&uirow->hdr);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, 
+                MSICOMPONENT* component, MSIEXTENSION* extension,
+                MSIVERB* verb, INT* Sequence )
+{
+    LPWSTR keyname;
+    HKEY key;
+    static const WCHAR szShell[] = {'s','h','e','l','l',0};
+    static const WCHAR szCommand[] = {'c','o','m','m','a','n','d',0};
+    static const WCHAR fmt[] = {'\"','%','s','\"',' ','%','s',0};
+    static const WCHAR fmt2[] = {'\"','%','s','\"',0};
+    LPWSTR command;
+    DWORD size;
+    LPWSTR advertise;
+
+    keyname = build_directory_name(4, progid, szShell, verb->Verb, szCommand);
+
+    TRACE("Making Key %s\n",debugstr_w(keyname));
+    RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
+    size = strlenW(component->FullKeypath);
+    if (verb->Argument)
+        size += strlenW(verb->Argument);
+     size += 4;
+
+     command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
+     if (verb->Argument)
+        sprintfW(command, fmt, component->FullKeypath, verb->Argument);
+     else
+        sprintfW(command, fmt2, component->FullKeypath);
+
+     RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)command, (strlenW(command)+1)*
+                     sizeof(WCHAR));
+     HeapFree(GetProcessHeap(),0,command);
+
+     advertise = create_component_advertise_string(package, component, 
+                        package->features[extension->FeatureIndex].Feature);
+
+     size = strlenW(advertise);
+
+     if (verb->Argument)
+        size += strlenW(verb->Argument);
+     size += 4;
+
+     command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
+     memset(command,0,size*sizeof(WCHAR));
+
+     strcpyW(command,advertise);
+     if (verb->Argument)
+     {
+        static const WCHAR szSpace[] = {' ',0};
+         strcatW(command,szSpace);
+         strcatW(command,verb->Argument);
+     }
+
+     RegSetValueExW(key, szCommand, 0, REG_MULTI_SZ, (LPBYTE)command,
+                        (strlenW(command)+2)*sizeof(WCHAR));
+     
+     RegCloseKey(key);
+     HeapFree(GetProcessHeap(),0,keyname);
+     HeapFree(GetProcessHeap(),0,advertise);
+     HeapFree(GetProcessHeap(),0,command);
+
+     if (verb->Command)
+     {
+        keyname = build_directory_name(3, progid, szShell, verb->Verb);
+        RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
+        RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)verb->Command,
+                                    (strlenW(verb->Command)+1) *sizeof(WCHAR));
+        RegCloseKey(key);
+        HeapFree(GetProcessHeap(),0,keyname);
+     }
+
+     if (verb->Sequence != MSI_NULL_INTEGER)
+     {
+        if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
+        {
+            *Sequence = verb->Sequence;
+            keyname = build_directory_name(2, progid, szShell);
+            RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
+            RegSetValueExW(key,NULL,0,REG_SZ, (LPVOID)verb->Verb,
+                            (strlenW(verb->Verb)+1) *sizeof(WCHAR));
+            RegCloseKey(key);
+            HeapFree(GetProcessHeap(),0,keyname);
+        }
+    }
+    return ERROR_SUCCESS;
+}
+
+UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
+{
+    static const WCHAR szContentType[] = 
+        {'C','o','n','t','e','n','t',' ','T','y','p','e',0 };
+    HKEY hkey;
+    INT i;
+    MSIRECORD *uirow;
+    BOOL install_on_demand = TRUE;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    load_classes_and_such(package);
+
+    /* We need to set install_on_demand based on if the shell handles advertised
+     * shortcuts and the like. Because Mike McCormack is working on this i am
+     * going to default to TRUE
+     */
+    
+    for (i = 0; i < package->loaded_extensions; i++)
+    {
+        WCHAR extension[257];
+        INT index,f_index;
+     
+        index = package->extensions[i].ComponentIndex;
+        f_index = package->extensions[i].FeatureIndex;
+
+        if (index < 0)
+            continue;
+
+        /* 
+         * yes. MSDN says that these are based on _Feature_ not on
+         * Component.  So verify the feature is to be installed
+         */
+        if ((!ACTION_VerifyFeatureForAction(package, f_index,
+                                INSTALLSTATE_LOCAL)) &&
+             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
+                             f_index, INSTALLSTATE_ADVERTISED)))
+        {
+            TRACE("Skipping extension  %s reg due to disabled feature %s\n",
+                            debugstr_w(package->extensions[i].Extension),
+                            debugstr_w(package->features[f_index].Feature));
+
+            continue;
+        }
+
+        TRACE("Registering extension %s index %i\n",
+                        debugstr_w(package->extensions[i].Extension), i);
+
+        package->extensions[i].Installed = TRUE;
+
+        /* this is only registered if the extension has at least 1 verb
+         * according to MSDN
+         */
+        if (package->extensions[i].ProgIDIndex >= 0 &&
+                package->extensions[i].VerbCount > 0)
+           mark_progid_for_install(package, package->extensions[i].ProgIDIndex);
+
+        if (package->extensions[i].MIMEIndex >= 0)
+           mark_mime_for_install(package, package->extensions[i].MIMEIndex);
+
+        extension[0] = '.';
+        extension[1] = 0;
+        strcatW(extension,package->extensions[i].Extension);
+
+        RegCreateKeyW(HKEY_CLASSES_ROOT,extension,&hkey);
+
+        if (package->extensions[i].MIMEIndex >= 0)
+        {
+            RegSetValueExW(hkey,szContentType,0,REG_SZ,
+                            (LPVOID)package->mimes[package->extensions[i].
+                                MIMEIndex].ContentType,
+                           (strlenW(package->mimes[package->extensions[i].
+                                    MIMEIndex].ContentType)+1)*sizeof(WCHAR));
+        }
+
+        if (package->extensions[i].ProgIDIndex >= 0 || 
+            package->extensions[i].ProgIDText)
+        {
+            static const WCHAR szSN[] = 
+                {'\\','S','h','e','l','l','N','e','w',0};
+            HKEY hkey2;
+            LPWSTR newkey;
+            LPCWSTR progid;
+            INT v;
+            INT Sequence = MSI_NULL_INTEGER;
+            
+            if (package->extensions[i].ProgIDIndex >= 0)
+                progid = package->progids[package->extensions[i].
+                    ProgIDIndex].ProgID;
+            else
+                progid = package->extensions[i].ProgIDText;
+
+            RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid,
+                           (strlenW(progid)+1)*sizeof(WCHAR));
+
+            newkey = HeapAlloc(GetProcessHeap(),0,
+                           (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); 
+
+            strcpyW(newkey,progid);
+            strcatW(newkey,szSN);
+            RegCreateKeyW(hkey,newkey,&hkey2);
+            RegCloseKey(hkey2);
+
+            HeapFree(GetProcessHeap(),0,newkey);
+
+            /* do all the verbs */
+            for (v = 0; v < package->extensions[i].VerbCount; v++)
+                register_verb(package, progid, 
+                              &package->components[index],
+                              &package->extensions[i],
+                              &package->verbs[package->extensions[i].Verbs[v]], 
+                              &Sequence);
+        }
+        
+        RegCloseKey(hkey);
+
+        uirow = MSI_CreateRecord(1);
+        MSI_RecordSetStringW(uirow,1,package->extensions[i].Extension);
+        ui_actiondata(package,szRegisterExtensionInfo,uirow);
+        msiobj_release(&uirow->hdr);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
+{
+    static const WCHAR szExten[] = 
+        {'E','x','t','e','n','s','i','o','n',0 };
+    HKEY hkey;
+    INT i;
+    MSIRECORD *uirow;
+
+    if (!package)
+        return ERROR_INVALID_HANDLE;
+
+    load_classes_and_such(package);
+
+    for (i = 0; i < package->loaded_mimes; i++)
+    {
+        WCHAR extension[257];
+        LPCWSTR exten;
+        LPCWSTR mime;
+        static const WCHAR fmt[] = 
+            {'M','I','M','E','\\','D','a','t','a','b','a','s','e','\\',
+             'C','o','n','t','e','n','t',' ','T','y','p','e','\\', '%','s',0};
+        LPWSTR key;
+
+        /* 
+         * check if the MIME is to be installed. Either as requesed by an
+         * extension or Class
+         */
+        package->mimes[i].InstallMe =  ((package->mimes[i].InstallMe) ||
+              (package->mimes[i].ClassIndex >= 0 &&
+              package->classes[package->mimes[i].ClassIndex].Installed) ||
+              (package->mimes[i].ExtensionIndex >=0 &&
+              package->extensions[package->mimes[i].ExtensionIndex].Installed));
+
+        if (!package->mimes[i].InstallMe)
+        {
+            TRACE("MIME %s not scheduled to be installed\n",
+                             debugstr_w(package->mimes[i].ContentType));
+            continue;
+        }
+        
+        mime = package->mimes[i].ContentType;
+        exten = package->extensions[package->mimes[i].ExtensionIndex].Extension;
+        extension[0] = '.';
+        extension[1] = 0;
+        strcatW(extension,exten);
+
+        key = HeapAlloc(GetProcessHeap(),0,(strlenW(mime)+strlenW(fmt)+1) *
+                                            sizeof(WCHAR));
+        sprintfW(key,fmt,mime);
+        RegCreateKeyW(HKEY_CLASSES_ROOT,key,&hkey);
+        RegSetValueExW(hkey,szExten,0,REG_SZ,(LPVOID)extension,
+                           (strlenW(extension)+1)*sizeof(WCHAR));
+
+        HeapFree(GetProcessHeap(),0,key);
+
+        if (package->mimes[i].CLSID[0])
+        {
+            FIXME("Handle non null for field 3\n");
+        }
+
+        RegCloseKey(hkey);
+
+        uirow = MSI_CreateRecord(2);
+        MSI_RecordSetStringW(uirow,1,package->mimes[i].ContentType);
+        MSI_RecordSetStringW(uirow,2,exten);
+        ui_actiondata(package,szRegisterMIMEInfo,uirow);
+        msiobj_release(&uirow->hdr);
+    }
+
+    return ERROR_SUCCESS;
+}
+


More information about the wine-patches mailing list