ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

classes.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2005 Aric Stewart for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 /* Actions handled in this module:
00022  *
00023  * RegisterClassInfo
00024  * RegisterProgIdInfo
00025  * RegisterExtensionInfo
00026  * RegisterMIMEInfo
00027  * UnregisterClassInfo
00028  * UnregisterProgIdInfo
00029  * UnregisterExtensionInfo
00030  * UnregisterMIMEInfo
00031  */
00032 
00033 #include <stdarg.h>
00034 
00035 #include "windef.h"
00036 #include "winbase.h"
00037 #include "winerror.h"
00038 #include "winreg.h"
00039 #include "wine/debug.h"
00040 #include "msipriv.h"
00041 #include "winuser.h"
00042 #include "wine/unicode.h"
00043 
00044 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00045 
00046 static MSIAPPID *load_appid( MSIPACKAGE* package, MSIRECORD *row )
00047 {
00048     LPCWSTR buffer;
00049     MSIAPPID *appid;
00050 
00051     /* fill in the data */
00052 
00053     appid = msi_alloc_zero( sizeof(MSIAPPID) );
00054     if (!appid)
00055         return NULL;
00056     
00057     appid->AppID = msi_dup_record_field( row, 1 );
00058     TRACE("loading appid %s\n", debugstr_w( appid->AppID ));
00059 
00060     buffer = MSI_RecordGetString(row,2);
00061     deformat_string( package, buffer, &appid->RemoteServerName );
00062 
00063     appid->LocalServer = msi_dup_record_field(row,3);
00064     appid->ServiceParameters = msi_dup_record_field(row,4);
00065     appid->DllSurrogate = msi_dup_record_field(row,5);
00066 
00067     appid->ActivateAtStorage = !MSI_RecordIsNull(row,6);
00068     appid->RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
00069 
00070     list_add_tail( &package->appids, &appid->entry );
00071     
00072     return appid;
00073 }
00074 
00075 static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
00076 {
00077     static const WCHAR query[] = {
00078         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00079         '`','A','p','p','I','d','`',' ','W','H','E','R','E',' ',
00080         '`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0};
00081     MSIRECORD *row;
00082     MSIAPPID *appid;
00083 
00084     if (!name)
00085         return NULL;
00086 
00087     /* check for appids already loaded */
00088     LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
00089     {
00090         if (!strcmpiW( appid->AppID, name ))
00091         {
00092             TRACE("found appid %s %p\n", debugstr_w(name), appid);
00093             return appid;
00094         }
00095     }
00096     
00097     row = MSI_QueryGetRecord(package->db, query, name);
00098     if (!row)
00099         return NULL;
00100 
00101     appid = load_appid(package, row);
00102     msiobj_release(&row->hdr);
00103     return appid;
00104 }
00105 
00106 static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
00107 static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid );
00108 
00109 static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
00110 {
00111     MSIPROGID *progid;
00112     LPCWSTR buffer;
00113 
00114     /* fill in the data */
00115 
00116     progid = msi_alloc_zero( sizeof(MSIPROGID) );
00117     if (!progid)
00118         return NULL;
00119 
00120     list_add_tail( &package->progids, &progid->entry );
00121 
00122     progid->ProgID = msi_dup_record_field(row,1);
00123     TRACE("loading progid %s\n",debugstr_w(progid->ProgID));
00124 
00125     buffer = MSI_RecordGetString(row,2);
00126     progid->Parent = load_given_progid(package,buffer);
00127     if (progid->Parent == NULL && buffer)
00128         FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
00129 
00130     buffer = MSI_RecordGetString(row,3);
00131     progid->Class = load_given_class(package,buffer);
00132     if (progid->Class == NULL && buffer)
00133         FIXME("Unknown class %s\n",debugstr_w(buffer));
00134 
00135     progid->Description = msi_dup_record_field(row,4);
00136 
00137     if (!MSI_RecordIsNull(row,6))
00138     {
00139         INT icon_index = MSI_RecordGetInteger(row,6); 
00140         LPCWSTR FileName = MSI_RecordGetString(row,5);
00141         LPWSTR FilePath;
00142         static const WCHAR fmt[] = {'%','s',',','%','i',0};
00143 
00144         FilePath = msi_build_icon_path(package, FileName);
00145        
00146         progid->IconPath = msi_alloc( (strlenW(FilePath)+10)* sizeof(WCHAR) );
00147 
00148         sprintfW(progid->IconPath,fmt,FilePath,icon_index);
00149 
00150         msi_free(FilePath);
00151     }
00152     else
00153     {
00154         buffer = MSI_RecordGetString(row,5);
00155         if (buffer)
00156             progid->IconPath = msi_build_icon_path(package, buffer);
00157     }
00158 
00159     progid->CurVer = NULL;
00160     progid->VersionInd = NULL;
00161 
00162     /* if we have a parent then we may be that parents CurVer */
00163     if (progid->Parent && progid->Parent != progid)
00164     {
00165         MSIPROGID *parent = progid->Parent;
00166 
00167         while (parent->Parent && parent->Parent != parent)
00168             parent = parent->Parent;
00169 
00170         /* FIXME: need to determine if we are really the CurVer */
00171 
00172         progid->CurVer = parent;
00173         parent->VersionInd = progid;
00174     }
00175     
00176     return progid;
00177 }
00178 
00179 static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
00180 {
00181     static const WCHAR query[] = {
00182         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00183         '`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ',
00184         '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
00185     MSIPROGID *progid;
00186     MSIRECORD *row;
00187 
00188     if (!name)
00189         return NULL;
00190 
00191     /* check for progids already loaded */
00192     LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
00193     {
00194         if (!strcmpiW( progid->ProgID, name ))
00195         {
00196             TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
00197             return progid;
00198         }
00199     }
00200     
00201     row = MSI_QueryGetRecord( package->db, query, name );
00202     if (!row)
00203         return NULL;
00204 
00205     progid = load_progid(package, row);
00206     msiobj_release(&row->hdr);
00207     return progid;
00208 }
00209 
00210 static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
00211 {
00212     MSICLASS *cls;
00213     DWORD i;
00214     LPCWSTR buffer;
00215 
00216     /* fill in the data */
00217 
00218     cls = msi_alloc_zero( sizeof(MSICLASS) );
00219     if (!cls)
00220         return NULL;
00221 
00222     list_add_tail( &package->classes, &cls->entry );
00223 
00224     cls->clsid = msi_dup_record_field( row, 1 );
00225     TRACE("loading class %s\n",debugstr_w(cls->clsid));
00226     cls->Context = msi_dup_record_field( row, 2 );
00227     buffer = MSI_RecordGetString(row,3);
00228     cls->Component = msi_get_loaded_component( package, buffer );
00229 
00230     cls->ProgIDText = msi_dup_record_field(row,4);
00231     cls->ProgID = load_given_progid(package, cls->ProgIDText);
00232 
00233     cls->Description = msi_dup_record_field(row,5);
00234 
00235     buffer = MSI_RecordGetString(row,6);
00236     if (buffer)
00237         cls->AppID = load_given_appid(package, buffer);
00238 
00239     cls->FileTypeMask = msi_dup_record_field(row,7);
00240 
00241     if (!MSI_RecordIsNull(row,9))
00242     {
00243 
00244         INT icon_index = MSI_RecordGetInteger(row,9); 
00245         LPCWSTR FileName = MSI_RecordGetString(row,8);
00246         LPWSTR FilePath;
00247         static const WCHAR fmt[] = {'%','s',',','%','i',0};
00248 
00249         FilePath = msi_build_icon_path(package, FileName);
00250        
00251         cls->IconPath = msi_alloc( (strlenW(FilePath)+5)* sizeof(WCHAR) );
00252 
00253         sprintfW(cls->IconPath,fmt,FilePath,icon_index);
00254 
00255         msi_free(FilePath);
00256     }
00257     else
00258     {
00259         buffer = MSI_RecordGetString(row,8);
00260         if (buffer)
00261             cls->IconPath = msi_build_icon_path(package, buffer);
00262     }
00263 
00264     if (!MSI_RecordIsNull(row,10))
00265     {
00266         i = MSI_RecordGetInteger(row,10);
00267         if (i != MSI_NULL_INTEGER && i > 0 &&  i < 4)
00268         {
00269             static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
00270             static const WCHAR ole32[] = {'o','l','e','3','2','.','d','l','l',0};
00271 
00272             switch(i)
00273             {
00274                 case 1:
00275                     cls->DefInprocHandler = strdupW(ole2);
00276                     break;
00277                 case 2:
00278                     cls->DefInprocHandler32 = strdupW(ole32);
00279                     break;
00280                 case 3:
00281                     cls->DefInprocHandler = strdupW(ole2);
00282                     cls->DefInprocHandler32 = strdupW(ole32);
00283                     break;
00284             }
00285         }
00286         else
00287         {
00288             cls->DefInprocHandler32 = msi_dup_record_field( row, 10 );
00289             msi_reduce_to_long_filename( cls->DefInprocHandler32 );
00290         }
00291     }
00292     buffer = MSI_RecordGetString(row,11);
00293     deformat_string(package,buffer,&cls->Argument);
00294 
00295     buffer = MSI_RecordGetString(row,12);
00296     cls->Feature = msi_get_loaded_feature(package, buffer);
00297 
00298     cls->Attributes = MSI_RecordGetInteger(row,13);
00299     
00300     return cls;
00301 }
00302 
00303 /*
00304  * the Class table has 3 primary keys. Generally it is only 
00305  * referenced through the first CLSID key. However when loading
00306  * all of the classes we need to make sure we do not ignore rows
00307  * with other Context and ComponentIndexs 
00308  */
00309 static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
00310 {
00311     static const WCHAR query[] = {
00312         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00313         '`','C','l','a','s','s','`',' ','W','H','E','R','E',' ',
00314         '`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0};
00315     MSICLASS *cls;
00316     MSIRECORD *row;
00317 
00318     if (!classid)
00319         return NULL;
00320     
00321     /* check for classes already loaded */
00322     LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
00323     {
00324         if (!strcmpiW( cls->clsid, classid ))
00325         {
00326             TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
00327             return cls;
00328         }
00329     }
00330 
00331     row = MSI_QueryGetRecord(package->db, query, classid);
00332     if (!row)
00333         return NULL;
00334 
00335     cls = load_class(package, row);
00336     msiobj_release(&row->hdr);
00337     return cls;
00338 }
00339 
00340 static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR extension );
00341 
00342 static MSIMIME *load_mime( MSIPACKAGE* package, MSIRECORD *row )
00343 {
00344     LPCWSTR extension;
00345     MSIMIME *mt;
00346 
00347     /* fill in the data */
00348 
00349     mt = msi_alloc_zero( sizeof(MSIMIME) );
00350     if (!mt)
00351         return mt;
00352 
00353     mt->ContentType = msi_dup_record_field( row, 1 ); 
00354     TRACE("loading mime %s\n", debugstr_w(mt->ContentType));
00355 
00356     extension = MSI_RecordGetString( row, 2 );
00357     mt->Extension = load_given_extension( package, extension );
00358     mt->suffix = strdupW( extension );
00359 
00360     mt->clsid = msi_dup_record_field( row, 3 );
00361     mt->Class = load_given_class( package, mt->clsid );
00362 
00363     list_add_tail( &package->mimes, &mt->entry );
00364 
00365     return mt;
00366 }
00367 
00368 static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
00369 {
00370     static const WCHAR query[] = {
00371         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00372         '`','M','I','M','E','`',' ','W','H','E','R','E',' ',
00373         '`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ','\'','%','s','\'',0};
00374     MSIRECORD *row;
00375     MSIMIME *mt;
00376 
00377     if (!mime)
00378         return NULL;
00379     
00380     /* check for mime already loaded */
00381     LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
00382     {
00383         if (!strcmpiW( mt->ContentType, mime ))
00384         {
00385             TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
00386             return mt;
00387         }
00388     }
00389     
00390     row = MSI_QueryGetRecord(package->db, query, mime);
00391     if (!row)
00392         return NULL;
00393 
00394     mt = load_mime(package, row);
00395     msiobj_release(&row->hdr);
00396     return mt;
00397 }
00398 
00399 static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
00400 {
00401     MSIEXTENSION *ext;
00402     LPCWSTR buffer;
00403 
00404     /* fill in the data */
00405 
00406     ext = msi_alloc_zero( sizeof(MSIEXTENSION) );
00407     if (!ext)
00408         return NULL;
00409 
00410     list_init( &ext->verbs );
00411 
00412     list_add_tail( &package->extensions, &ext->entry );
00413 
00414     ext->Extension = msi_dup_record_field( row, 1 );
00415     TRACE("loading extension %s\n", debugstr_w(ext->Extension));
00416 
00417     buffer = MSI_RecordGetString( row, 2 );
00418     ext->Component = msi_get_loaded_component( package, buffer );
00419 
00420     ext->ProgIDText = msi_dup_record_field( row, 3 );
00421     ext->ProgID = load_given_progid( package, ext->ProgIDText );
00422 
00423     buffer = MSI_RecordGetString( row, 4 );
00424     ext->Mime = load_given_mime( package, buffer );
00425 
00426     buffer = MSI_RecordGetString(row,5);
00427     ext->Feature = msi_get_loaded_feature( package, buffer );
00428 
00429     return ext;
00430 }
00431 
00432 /*
00433  * While the extension table has 2 primary keys, this function is only looking
00434  * at the Extension key which is what is referenced as a foreign key
00435  */
00436 static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
00437 {
00438     static const WCHAR query[] = {
00439         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
00440         '`','E','x','t','e','n','s','i','o','n','`',' ','W','H','E','R','E',' ',
00441         '`','E','x','t','e','n','s','i','o','n','`',' ','=',' ','\'','%','s','\'',0};
00442     MSIEXTENSION *ext;
00443     MSIRECORD *row;
00444 
00445     if (!name)
00446         return NULL;
00447 
00448     if (name[0] == '.')
00449         name++;
00450 
00451     /* check for extensions already loaded */
00452     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
00453     {
00454         if (!strcmpiW( ext->Extension, name ))
00455         {
00456             TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
00457             return ext;
00458         }
00459     }
00460     
00461     row = MSI_QueryGetRecord( package->db, query, name );
00462     if (!row)
00463         return NULL;
00464 
00465     ext = load_extension(package, row);
00466     msiobj_release(&row->hdr);
00467     return ext;
00468 }
00469 
00470 static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
00471 {
00472     MSIPACKAGE* package = param;
00473     MSIVERB *verb;
00474     LPCWSTR buffer;
00475     MSIEXTENSION *extension;
00476 
00477     buffer = MSI_RecordGetString(row,1);
00478     extension = load_given_extension( package, buffer );
00479     if (!extension)
00480     {
00481         ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
00482         return ERROR_SUCCESS;
00483     }
00484 
00485     /* fill in the data */
00486 
00487     verb = msi_alloc_zero( sizeof(MSIVERB) );
00488     if (!verb)
00489         return ERROR_OUTOFMEMORY;
00490 
00491     verb->Verb = msi_dup_record_field(row,2);
00492     TRACE("loading verb %s\n",debugstr_w(verb->Verb));
00493     verb->Sequence = MSI_RecordGetInteger(row,3);
00494 
00495     buffer = MSI_RecordGetString(row,4);
00496     deformat_string(package,buffer,&verb->Command);
00497 
00498     buffer = MSI_RecordGetString(row,5);
00499     deformat_string(package,buffer,&verb->Argument);
00500 
00501     /* associate the verb with the correct extension */
00502     list_add_tail( &extension->verbs, &verb->entry );
00503     
00504     return ERROR_SUCCESS;
00505 }
00506 
00507 static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
00508 {
00509     MSICOMPONENT *comp;
00510     LPCWSTR clsid;
00511     LPCWSTR context;
00512     LPCWSTR buffer;
00513     MSIPACKAGE* package = param;
00514     MSICLASS *cls;
00515     BOOL match = FALSE;
00516 
00517     clsid = MSI_RecordGetString(rec,1);
00518     context = MSI_RecordGetString(rec,2);
00519     buffer = MSI_RecordGetString(rec,3);
00520     comp = msi_get_loaded_component(package, buffer);
00521 
00522     LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
00523     {
00524         if (strcmpiW( clsid, cls->clsid ))
00525             continue;
00526         if (strcmpW( context, cls->Context ))
00527             continue;
00528         if (comp == cls->Component)
00529         {
00530             match = TRUE;
00531             break;
00532         }
00533     }
00534     
00535     if (!match)
00536         load_class(package, rec);
00537 
00538     return ERROR_SUCCESS;
00539 }
00540 
00541 static UINT load_all_classes( MSIPACKAGE *package )
00542 {
00543     static const WCHAR query[] = {
00544         'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ','`','C','l','a','s','s','`',0};
00545     MSIQUERY *view;
00546     UINT rc;
00547 
00548     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00549     if (rc != ERROR_SUCCESS)
00550         return ERROR_SUCCESS;
00551 
00552     rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
00553     msiobj_release(&view->hdr);
00554     return rc;
00555 }
00556 
00557 static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
00558 {
00559     MSICOMPONENT *comp;
00560     LPCWSTR buffer;
00561     LPCWSTR extension;
00562     MSIPACKAGE* package = param;
00563     BOOL match = FALSE;
00564     MSIEXTENSION *ext;
00565 
00566     extension = MSI_RecordGetString(rec,1);
00567     buffer = MSI_RecordGetString(rec,2);
00568     comp = msi_get_loaded_component(package, buffer);
00569 
00570     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
00571     {
00572         if (strcmpiW(extension, ext->Extension))
00573             continue;
00574         if (comp == ext->Component)
00575         {
00576             match = TRUE;
00577             break;
00578         }
00579     }
00580 
00581     if (!match)
00582         load_extension(package, rec);
00583 
00584     return ERROR_SUCCESS;
00585 }
00586 
00587 static UINT load_all_extensions( MSIPACKAGE *package )
00588 {
00589     static const WCHAR query[] = {
00590         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','E','x','t','e','n','s','i','o','n','`',0};
00591     MSIQUERY *view;
00592     UINT rc;
00593 
00594     rc = MSI_DatabaseOpenViewW( package->db, query, &view );
00595     if (rc != ERROR_SUCCESS)
00596         return ERROR_SUCCESS;
00597 
00598     rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
00599     msiobj_release(&view->hdr);
00600     return rc;
00601 }
00602 
00603 static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
00604 {
00605     LPCWSTR buffer;
00606     MSIPACKAGE* package = param;
00607 
00608     buffer = MSI_RecordGetString(rec,1);
00609     load_given_progid(package,buffer);
00610     return ERROR_SUCCESS;
00611 }
00612 
00613 static UINT load_all_progids( MSIPACKAGE *package )
00614 {
00615     static const WCHAR query[] = {
00616         'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ','F','R','O','M',' ',
00617         '`','P','r','o','g','I','d','`',0};
00618     MSIQUERY *view;
00619     UINT rc;
00620 
00621     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00622     if (rc != ERROR_SUCCESS)
00623         return ERROR_SUCCESS;
00624 
00625     rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
00626     msiobj_release(&view->hdr);
00627     return rc;
00628 }
00629 
00630 static UINT load_all_verbs( MSIPACKAGE *package )
00631 {
00632     static const WCHAR query[] = {
00633         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','V','e','r','b','`',0};
00634     MSIQUERY *view;
00635     UINT rc;
00636 
00637     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00638     if (rc != ERROR_SUCCESS)
00639         return ERROR_SUCCESS;
00640 
00641     rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
00642     msiobj_release(&view->hdr);
00643     return rc;
00644 }
00645 
00646 static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
00647 {
00648     LPCWSTR buffer;
00649     MSIPACKAGE* package = param;
00650 
00651     buffer = MSI_RecordGetString(rec,1);
00652     load_given_mime(package,buffer);
00653     return ERROR_SUCCESS;
00654 }
00655 
00656 static UINT load_all_mimes( MSIPACKAGE *package )
00657 {
00658     static const WCHAR query[] = {
00659         'S','E','L','E','C','T',' ','`','C','o','n','t','e','n','t','T','y','p','e','`',' ',
00660         'F','R','O','M',' ','`','M','I','M','E','`',0};
00661     MSIQUERY *view;
00662     UINT rc;
00663 
00664     rc = MSI_DatabaseOpenViewW(package->db, query, &view);
00665     if (rc != ERROR_SUCCESS)
00666         return ERROR_SUCCESS;
00667 
00668     rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
00669     msiobj_release(&view->hdr);
00670     return rc;
00671 }
00672 
00673 static UINT load_classes_and_such( MSIPACKAGE *package )
00674 {
00675     UINT r;
00676 
00677     TRACE("Loading all the class info and related tables\n");
00678 
00679     /* check if already loaded */
00680     if (!list_empty( &package->classes ) ||
00681         !list_empty( &package->mimes ) ||
00682         !list_empty( &package->extensions ) ||
00683         !list_empty( &package->progids )) return ERROR_SUCCESS;
00684 
00685     r = load_all_classes( package );
00686     if (r != ERROR_SUCCESS) return r;
00687 
00688     r = load_all_extensions( package );
00689     if (r != ERROR_SUCCESS) return r;
00690 
00691     r = load_all_progids( package );
00692     if (r != ERROR_SUCCESS) return r;
00693 
00694     /* these loads must come after the other loads */
00695     r = load_all_verbs( package );
00696     if (r != ERROR_SUCCESS) return r;
00697 
00698     return load_all_mimes( package );
00699 }
00700 
00701 static void mark_progid_for_install( MSIPACKAGE* package, MSIPROGID *progid )
00702 {
00703     MSIPROGID *child;
00704 
00705     if (!progid)
00706         return;
00707 
00708     if (progid->InstallMe)
00709         return;
00710 
00711     progid->InstallMe = TRUE;
00712 
00713     /* all children if this is a parent also install */
00714     LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
00715     {
00716         if (child->Parent == progid)
00717             mark_progid_for_install( package, child );
00718     }
00719 }
00720 
00721 static void mark_progid_for_uninstall( MSIPACKAGE *package, MSIPROGID *progid )
00722 {
00723     MSIPROGID *child;
00724 
00725     if (!progid)
00726         return;
00727 
00728     if (!progid->InstallMe)
00729         return;
00730 
00731     progid->InstallMe = FALSE;
00732 
00733     LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
00734     {
00735         if (child->Parent == progid)
00736             mark_progid_for_uninstall( package, child );
00737     }
00738 }
00739 
00740 static void mark_mime_for_install( MSIMIME *mime )
00741 {
00742     if (!mime)
00743         return;
00744     mime->InstallMe = TRUE;
00745 }
00746 
00747 static void mark_mime_for_uninstall( MSIMIME *mime )
00748 {
00749     if (!mime)
00750         return;
00751     mime->InstallMe = FALSE;
00752 }
00753 
00754 static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
00755 {
00756     static const WCHAR szRemoteServerName[] =
00757          {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
00758     static const WCHAR szLocalService[] =
00759          {'L','o','c','a','l','S','e','r','v','i','c','e',0};
00760     static const WCHAR szService[] =
00761          {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};
00762     static const WCHAR szDLL[] =
00763          {'D','l','l','S','u','r','r','o','g','a','t','e',0};
00764     static const WCHAR szActivate[] =
00765          {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0};
00766     static const WCHAR szY[] = {'Y',0};
00767     static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
00768     static const WCHAR szUser[] = 
00769          {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};
00770 
00771     HKEY hkey2,hkey3;
00772 
00773     RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
00774     RegCreateKeyW( hkey2, appid->AppID, &hkey3 );
00775     RegCloseKey(hkey2);
00776     msi_reg_set_val_str( hkey3, NULL, app );
00777 
00778     if (appid->RemoteServerName)
00779         msi_reg_set_val_str( hkey3, szRemoteServerName, appid->RemoteServerName );
00780 
00781     if (appid->LocalServer)
00782         msi_reg_set_val_str( hkey3, szLocalService, appid->LocalServer );
00783 
00784     if (appid->ServiceParameters)
00785         msi_reg_set_val_str( hkey3, szService, appid->ServiceParameters );
00786 
00787     if (appid->DllSurrogate)
00788         msi_reg_set_val_str( hkey3, szDLL, appid->DllSurrogate );
00789 
00790     if (appid->ActivateAtStorage)
00791         msi_reg_set_val_str( hkey3, szActivate, szY );
00792 
00793     if (appid->RunAsInteractiveUser)
00794         msi_reg_set_val_str( hkey3, szRunAs, szUser );
00795 
00796     RegCloseKey(hkey3);
00797     return ERROR_SUCCESS;
00798 }
00799 
00800 UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
00801 {
00802     static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
00803     const WCHAR *keypath;
00804     MSIRECORD *uirow;
00805     HKEY hkey, hkey2, hkey3;
00806     MSICLASS *cls;
00807     UINT r;
00808 
00809     r = load_classes_and_such( package );
00810     if (r != ERROR_SUCCESS)
00811         return r;
00812 
00813     if (is_64bit && package->platform == PLATFORM_INTEL)
00814         keypath = szWow6432NodeCLSID;
00815     else
00816         keypath = szCLSID;
00817 
00818     if (RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, &hkey) != ERROR_SUCCESS)
00819         return ERROR_FUNCTION_FAILED;
00820 
00821     LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
00822     {
00823         MSICOMPONENT *comp;
00824         MSIFILE *file;
00825         DWORD size;
00826         LPWSTR argument;
00827         MSIFEATURE *feature;
00828 
00829         comp = cls->Component;
00830         if ( !comp )
00831             continue;
00832 
00833         if (!comp->Enabled)
00834         {
00835             TRACE("component is disabled\n");
00836             continue;
00837         }
00838 
00839         feature = cls->Feature;
00840         if (!feature)
00841             continue;
00842 
00843         feature->Action = msi_get_feature_action( package, feature );
00844         if (feature->Action != INSTALLSTATE_LOCAL &&
00845             feature->Action != INSTALLSTATE_ADVERTISED )
00846         {
00847             TRACE("feature %s not scheduled for installation, skipping registration of class %s\n",
00848                   debugstr_w(feature->Feature), debugstr_w(cls->clsid));
00849             continue;
00850         }
00851 
00852         if (!comp->KeyPath || !(file = msi_get_loaded_file( package, comp->KeyPath )))
00853         {
00854             TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
00855             continue;
00856         }
00857         TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls);
00858 
00859         cls->Installed = TRUE;
00860         mark_progid_for_install( package, cls->ProgID );
00861 
00862         RegCreateKeyW( hkey, cls->clsid, &hkey2 );
00863 
00864         if (cls->Description)
00865             msi_reg_set_val_str( hkey2, NULL, cls->Description );
00866 
00867         RegCreateKeyW( hkey2, cls->Context, &hkey3 );
00868 
00869         /*
00870          * FIXME: Implement install on demand (advertised components).
00871          *
00872          * ole32.dll should call msi.MsiProvideComponentFromDescriptor()
00873          *  when it needs an InProcServer that doesn't exist.
00874          * The component advertise string should be in the "InProcServer" value.
00875          */
00876         size = lstrlenW( file->TargetPath )+1;
00877         if (cls->Argument)
00878             size += lstrlenW(cls->Argument)+1;
00879 
00880         argument = msi_alloc( size * sizeof(WCHAR) );
00881         lstrcpyW( argument, file->TargetPath );
00882 
00883         if (cls->Argument)
00884         {
00885             lstrcatW( argument, szSpace );
00886             lstrcatW( argument, cls->Argument );
00887         }
00888 
00889         msi_reg_set_val_str( hkey3, NULL, argument );
00890         msi_free(argument);
00891 
00892         RegCloseKey(hkey3);
00893 
00894         if (cls->ProgID || cls->ProgIDText)
00895         {
00896             LPCWSTR progid;
00897 
00898             if (cls->ProgID)
00899                 progid = cls->ProgID->ProgID;
00900             else
00901                 progid = cls->ProgIDText;
00902 
00903             msi_reg_set_subkey_val( hkey2, szProgID, NULL, progid );
00904 
00905             if (cls->ProgID && cls->ProgID->VersionInd)
00906             {
00907                 msi_reg_set_subkey_val( hkey2, szVIProgID, NULL, 
00908                                         cls->ProgID->VersionInd->ProgID );
00909             }
00910         }
00911 
00912         if (cls->AppID)
00913         {
00914             MSIAPPID *appid = cls->AppID;
00915             msi_reg_set_val_str( hkey2, szAppID, appid->AppID );
00916             register_appid( appid, cls->Description );
00917         }
00918 
00919         if (cls->IconPath)
00920             msi_reg_set_subkey_val( hkey2, szDefaultIcon, NULL, cls->IconPath );
00921 
00922         if (cls->DefInprocHandler)
00923             msi_reg_set_subkey_val( hkey2, szInprocHandler, NULL, cls->DefInprocHandler );
00924 
00925         if (cls->DefInprocHandler32)
00926             msi_reg_set_subkey_val( hkey2, szInprocHandler32, NULL, cls->DefInprocHandler32 );
00927         
00928         RegCloseKey(hkey2);
00929 
00930         /* if there is a FileTypeMask, register the FileType */
00931         if (cls->FileTypeMask)
00932         {
00933             LPWSTR ptr, ptr2;
00934             LPWSTR keyname;
00935             INT index = 0;
00936             ptr = cls->FileTypeMask;
00937             while (ptr && *ptr)
00938             {
00939                 ptr2 = strchrW(ptr,';');
00940                 if (ptr2)
00941                     *ptr2 = 0;
00942                 keyname = msi_alloc( (strlenW(szFileType_fmt) + strlenW(cls->clsid) + 4) * sizeof(WCHAR));
00943                 sprintfW( keyname, szFileType_fmt, cls->clsid, index );
00944 
00945                 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, ptr );
00946                 msi_free(keyname);
00947 
00948                 if (ptr2)
00949                     ptr = ptr2+1;
00950                 else
00951                     ptr = NULL;
00952 
00953                 index ++;
00954             }
00955         }
00956         
00957         uirow = MSI_CreateRecord(1);
00958         MSI_RecordSetStringW( uirow, 1, cls->clsid );
00959         msi_ui_actiondata( package, szRegisterClassInfo, uirow );
00960         msiobj_release(&uirow->hdr);
00961     }
00962     RegCloseKey(hkey);
00963     return ERROR_SUCCESS;
00964 }
00965 
00966 UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
00967 {
00968     static const WCHAR szFileType[] = {'F','i','l','e','T','y','p','e','\\',0};
00969     const WCHAR *keypath;
00970     MSIRECORD *uirow;
00971     MSICLASS *cls;
00972     HKEY hkey, hkey2;
00973     UINT r;
00974 
00975     r = load_classes_and_such( package );
00976     if (r != ERROR_SUCCESS)
00977         return r;
00978 
00979     if (is_64bit && package->platform == PLATFORM_INTEL)
00980         keypath = szWow6432NodeCLSID;
00981     else
00982         keypath = szCLSID;
00983 
00984     if (RegOpenKeyW( HKEY_CLASSES_ROOT, keypath, &hkey ) != ERROR_SUCCESS)
00985         return ERROR_SUCCESS;
00986 
00987     LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
00988     {
00989         MSIFEATURE *feature;
00990         MSICOMPONENT *comp;
00991         LPWSTR filetype;
00992         LONG res;
00993 
00994         comp = cls->Component;
00995         if (!comp)
00996             continue;
00997 
00998         if (!comp->Enabled)
00999         {
01000             TRACE("component is disabled\n");
01001             continue;
01002         }
01003 
01004         feature = cls->Feature;
01005         if (!feature)
01006             continue;
01007 
01008         feature->Action = msi_get_feature_action( package, feature );
01009         if (feature->Action != INSTALLSTATE_ABSENT)
01010         {
01011             TRACE("feature %s not scheduled for removal, skipping unregistration of class %s\n",
01012                   debugstr_w(feature->Feature), debugstr_w(cls->clsid));
01013             continue;
01014         }
01015         TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls);
01016 
01017         cls->Installed = FALSE;
01018         mark_progid_for_uninstall( package, cls->ProgID );
01019 
01020         res = RegDeleteTreeW( hkey, cls->clsid );
01021         if (res != ERROR_SUCCESS)
01022             WARN("Failed to delete class key %d\n", res);
01023 
01024         if (cls->AppID)
01025         {
01026             res = RegOpenKeyW( HKEY_CLASSES_ROOT, szAppID, &hkey2 );
01027             if (res == ERROR_SUCCESS)
01028             {
01029                 res = RegDeleteKeyW( hkey2, cls->AppID->AppID );
01030                 if (res != ERROR_SUCCESS)
01031                     WARN("Failed to delete appid key %d\n", res);
01032                 RegCloseKey( hkey2 );
01033             }
01034         }
01035         if (cls->FileTypeMask)
01036         {
01037             filetype = msi_alloc( (strlenW( szFileType ) + strlenW( cls->clsid ) + 1) * sizeof(WCHAR) );
01038             if (filetype)
01039             {
01040                 strcpyW( filetype, szFileType );
01041                 strcatW( filetype, cls->clsid );
01042                 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
01043                 msi_free( filetype );
01044 
01045                 if (res != ERROR_SUCCESS)
01046                     WARN("Failed to delete file type %d\n", res);
01047             }
01048         }
01049 
01050         uirow = MSI_CreateRecord( 1 );
01051         MSI_RecordSetStringW( uirow, 1, cls->clsid );
01052         msi_ui_actiondata( package, szUnregisterClassInfo, uirow );
01053         msiobj_release( &uirow->hdr );
01054     }
01055     RegCloseKey( hkey );
01056     return ERROR_SUCCESS;
01057 }
01058 
01059 static LPCWSTR get_clsid_of_progid( const MSIPROGID *progid )
01060 {
01061     while (progid)
01062     {
01063         if (progid->Class)
01064             return progid->Class->clsid;
01065         if (progid->Parent == progid)
01066             break;
01067         progid = progid->Parent;
01068     }
01069     return NULL;
01070 }
01071 
01072 static UINT register_progid( const MSIPROGID* progid )
01073 {
01074     static const WCHAR szCurVer[] = {'C','u','r','V','e','r',0};
01075     HKEY hkey = 0;
01076     UINT rc;
01077 
01078     rc = RegCreateKeyW( HKEY_CLASSES_ROOT, progid->ProgID, &hkey );
01079     if (rc == ERROR_SUCCESS)
01080     {
01081         LPCWSTR clsid = get_clsid_of_progid( progid );
01082 
01083         if (clsid)
01084             msi_reg_set_subkey_val( hkey, szCLSID, NULL, clsid );
01085         else
01086             TRACE("%s has no class\n", debugstr_w( progid->ProgID ) );
01087 
01088         if (progid->Description)
01089             msi_reg_set_val_str( hkey, NULL, progid->Description );
01090 
01091         if (progid->IconPath)
01092             msi_reg_set_subkey_val( hkey, szDefaultIcon, NULL, progid->IconPath );
01093 
01094         /* write out the current version */
01095         if (progid->CurVer)
01096             msi_reg_set_subkey_val( hkey, szCurVer, NULL, progid->CurVer->ProgID );
01097 
01098         RegCloseKey(hkey);
01099     }
01100     else
01101         ERR("failed to create key %s\n", debugstr_w( progid->ProgID ) );
01102 
01103     return rc;
01104 }
01105 
01106 UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
01107 {
01108     MSIPROGID *progid;
01109     MSIRECORD *uirow;
01110     UINT r;
01111 
01112     r = load_classes_and_such( package );
01113     if (r != ERROR_SUCCESS)
01114         return r;
01115 
01116     LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
01117     {
01118         /* check if this progid is to be installed */
01119         if (progid->Class && progid->Class->Installed)
01120             progid->InstallMe = TRUE;
01121 
01122         if (!progid->InstallMe)
01123         {
01124             TRACE("progid %s not scheduled to be installed\n",
01125                              debugstr_w(progid->ProgID));
01126             continue;
01127         }
01128        
01129         TRACE("Registering progid %s\n", debugstr_w(progid->ProgID));
01130 
01131         register_progid( progid );
01132 
01133         uirow = MSI_CreateRecord( 1 );
01134         MSI_RecordSetStringW( uirow, 1, progid->ProgID );
01135         msi_ui_actiondata( package, szRegisterProgIdInfo, uirow );
01136         msiobj_release( &uirow->hdr );
01137     }
01138     return ERROR_SUCCESS;
01139 }
01140 
01141 UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
01142 {
01143     MSIPROGID *progid;
01144     MSIRECORD *uirow;
01145     LONG res;
01146     UINT r;
01147 
01148     r = load_classes_and_such( package );
01149     if (r != ERROR_SUCCESS)
01150         return r;
01151 
01152     LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
01153     {
01154         /* check if this progid is to be removed */
01155         if (progid->Class && !progid->Class->Installed)
01156             progid->InstallMe = FALSE;
01157 
01158         if (progid->InstallMe)
01159         {
01160             TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID));
01161             continue;
01162         }
01163 
01164         TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
01165 
01166         res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
01167         if (res != ERROR_SUCCESS)
01168             TRACE("Failed to delete progid key %d\n", res);
01169 
01170         uirow = MSI_CreateRecord( 1 );
01171         MSI_RecordSetStringW( uirow, 1, progid->ProgID );
01172         msi_ui_actiondata( package, szUnregisterProgIdInfo, uirow );
01173         msiobj_release( &uirow->hdr );
01174     }
01175     return ERROR_SUCCESS;
01176 }
01177 
01178 static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, 
01179                 MSICOMPONENT* component, const MSIEXTENSION* extension,
01180                 MSIVERB* verb, INT* Sequence )
01181 {
01182     LPWSTR keyname;
01183     HKEY key;
01184     static const WCHAR szShell[] = {'s','h','e','l','l',0};
01185     static const WCHAR szCommand[] = {'c','o','m','m','a','n','d',0};
01186     static const WCHAR fmt[] = {'\"','%','s','\"',' ','%','s',0};
01187     static const WCHAR fmt2[] = {'\"','%','s','\"',0};
01188     LPWSTR command;
01189     DWORD size;
01190     LPWSTR advertise;
01191 
01192     keyname = msi_build_directory_name(4, progid, szShell, verb->Verb, szCommand);
01193 
01194     TRACE("Making Key %s\n",debugstr_w(keyname));
01195     RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
01196     size = strlenW(component->FullKeypath);
01197     if (verb->Argument)
01198         size += strlenW(verb->Argument);
01199      size += 4;
01200 
01201      command = msi_alloc(size * sizeof (WCHAR));
01202      if (verb->Argument)
01203         sprintfW(command, fmt, component->FullKeypath, verb->Argument);
01204      else
01205         sprintfW(command, fmt2, component->FullKeypath);
01206 
01207      msi_reg_set_val_str( key, NULL, command );
01208      msi_free(command);
01209 
01210      advertise = msi_create_component_advertise_string(package, component,
01211                                                        extension->Feature->Feature);
01212      size = strlenW(advertise);
01213 
01214      if (verb->Argument)
01215          size += strlenW(verb->Argument);
01216      size += 4;
01217 
01218      command = msi_alloc_zero(size * sizeof (WCHAR));
01219 
01220      strcpyW(command,advertise);
01221      if (verb->Argument)
01222      {
01223          strcatW(command,szSpace);
01224          strcatW(command,verb->Argument);
01225      }
01226 
01227      msi_reg_set_val_multi_str( key, szCommand, command );
01228      
01229      RegCloseKey(key);
01230      msi_free(keyname);
01231      msi_free(advertise);
01232      msi_free(command);
01233 
01234      if (verb->Command)
01235      {
01236         keyname = msi_build_directory_name( 3, progid, szShell, verb->Verb );
01237         msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Command );
01238         msi_free(keyname);
01239      }
01240 
01241      if (verb->Sequence != MSI_NULL_INTEGER)
01242      {
01243         if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
01244         {
01245             *Sequence = verb->Sequence;
01246             keyname = msi_build_directory_name( 2, progid, szShell );
01247             msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Verb );
01248             msi_free(keyname);
01249         }
01250     }
01251     return ERROR_SUCCESS;
01252 }
01253 
01254 UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
01255 {
01256     static const WCHAR szContentType[] = {'C','o','n','t','e','n','t',' ','T','y','p','e',0};
01257     HKEY hkey = NULL;
01258     MSIEXTENSION *ext;
01259     MSIRECORD *uirow;
01260     BOOL install_on_demand = TRUE;
01261     LONG res;
01262     UINT r;
01263 
01264     r = load_classes_and_such( package );
01265     if (r != ERROR_SUCCESS)
01266         return r;
01267 
01268     /* We need to set install_on_demand based on if the shell handles advertised
01269      * shortcuts and the like. Because Mike McCormack is working on this i am
01270      * going to default to TRUE
01271      */
01272     
01273     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
01274     {
01275         LPWSTR extension;
01276         MSIFEATURE *feature;
01277      
01278         if (!ext->Component)
01279             continue;
01280 
01281         if (!ext->Component->Enabled)
01282         {
01283             TRACE("component is disabled\n");
01284             continue;
01285         }
01286 
01287         feature = ext->Feature;
01288         if (!feature)
01289             continue;
01290 
01291         /* 
01292          * yes. MSDN says that these are based on _Feature_ not on
01293          * Component.  So verify the feature is to be installed
01294          */
01295         feature->Action = msi_get_feature_action( package, feature );
01296         if (feature->Action != INSTALLSTATE_LOCAL &&
01297             !(install_on_demand && feature->Action == INSTALLSTATE_ADVERTISED))
01298         {
01299             TRACE("feature %s not scheduled for installation, skipping registration of extension %s\n",
01300                   debugstr_w(feature->Feature), debugstr_w(ext->Extension));
01301             continue;
01302         }
01303         TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext);
01304 
01305         ext->Installed = TRUE;
01306 
01307         /* this is only registered if the extension has at least 1 verb
01308          * according to MSDN
01309          */
01310         if (ext->ProgID && !list_empty( &ext->verbs ) )
01311             mark_progid_for_install( package, ext->ProgID );
01312 
01313         mark_mime_for_install(ext->Mime);
01314 
01315         extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
01316         if (extension)
01317         {
01318             extension[0] = '.';
01319             strcpyW( extension + 1, ext->Extension );
01320             res = RegCreateKeyW( HKEY_CLASSES_ROOT, extension, &hkey );
01321             msi_free( extension );
01322             if (res != ERROR_SUCCESS)
01323                 WARN("Failed to create extension key %d\n", res);
01324         }
01325 
01326         if (ext->Mime)
01327             msi_reg_set_val_str( hkey, szContentType, ext->Mime->ContentType );
01328 
01329         if (ext->ProgID || ext->ProgIDText)
01330         {
01331             static const WCHAR szSN[] = 
01332                 {'\\','S','h','e','l','l','N','e','w',0};
01333             HKEY hkey2;
01334             LPWSTR newkey;
01335             LPCWSTR progid;
01336             MSIVERB *verb;
01337             INT Sequence = MSI_NULL_INTEGER;
01338             
01339             if (ext->ProgID)
01340                 progid = ext->ProgID->ProgID;
01341             else
01342                 progid = ext->ProgIDText;
01343 
01344             msi_reg_set_val_str( hkey, NULL, progid );
01345 
01346             newkey = msi_alloc( (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); 
01347 
01348             strcpyW(newkey,progid);
01349             strcatW(newkey,szSN);
01350             RegCreateKeyW(hkey,newkey,&hkey2);
01351             RegCloseKey(hkey2);
01352 
01353             msi_free(newkey);
01354 
01355             /* do all the verbs */
01356             LIST_FOR_EACH_ENTRY( verb, &ext->verbs, MSIVERB, entry )
01357             {
01358                 register_verb( package, progid, ext->Component,
01359                                ext, verb, &Sequence);
01360             }
01361         }
01362         
01363         RegCloseKey(hkey);
01364 
01365         uirow = MSI_CreateRecord(1);
01366         MSI_RecordSetStringW( uirow, 1, ext->Extension );
01367         msi_ui_actiondata( package, szRegisterExtensionInfo, uirow );
01368         msiobj_release(&uirow->hdr);
01369     }
01370     return ERROR_SUCCESS;
01371 }
01372 
01373 UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
01374 {
01375     MSIEXTENSION *ext;
01376     MSIRECORD *uirow;
01377     LONG res;
01378     UINT r;
01379 
01380     r = load_classes_and_such( package );
01381     if (r != ERROR_SUCCESS)
01382         return r;
01383 
01384     LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
01385     {
01386         LPWSTR extension;
01387         MSIFEATURE *feature;
01388 
01389         if (!ext->Component)
01390             continue;
01391 
01392         if (!ext->Component->Enabled)
01393         {
01394             TRACE("component is disabled\n");
01395             continue;
01396         }
01397 
01398         feature = ext->Feature;
01399         if (!feature)
01400             continue;
01401 
01402         feature->Action = msi_get_feature_action( package, feature );
01403         if (feature->Action != INSTALLSTATE_ABSENT)
01404         {
01405             TRACE("feature %s not scheduled for removal, skipping unregistration of extension %s\n",
01406                   debugstr_w(feature->Feature), debugstr_w(ext->Extension));
01407             continue;
01408         }
01409         TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension));
01410 
01411         ext->Installed = FALSE;
01412 
01413         if (ext->ProgID && !list_empty( &ext->verbs ))
01414             mark_progid_for_uninstall( package, ext->ProgID );
01415 
01416         mark_mime_for_uninstall( ext->Mime );
01417 
01418         extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
01419         if (extension)
01420         {
01421             extension[0] = '.';
01422             strcpyW( extension + 1, ext->Extension );
01423             res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
01424             msi_free( extension );
01425             if (res != ERROR_SUCCESS)
01426                 WARN("Failed to delete extension key %d\n", res);
01427         }
01428 
01429         if (ext->ProgID || ext->ProgIDText)
01430         {
01431             static const WCHAR shellW[] = {'\\','s','h','e','l','l',0};
01432             LPCWSTR progid;
01433             LPWSTR progid_shell;
01434 
01435             if (ext->ProgID)
01436                 progid = ext->ProgID->ProgID;
01437             else
01438                 progid = ext->ProgIDText;
01439 
01440             progid_shell = msi_alloc( (strlenW( progid ) + strlenW( shellW ) + 1) * sizeof(WCHAR) );
01441             if (progid_shell)
01442             {
01443                 strcpyW( progid_shell, progid );
01444                 strcatW( progid_shell, shellW );
01445                 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
01446                 msi_free( progid_shell );
01447                 if (res != ERROR_SUCCESS)
01448                     WARN("Failed to delete shell key %d\n", res);
01449                 RegDeleteKeyW( HKEY_CLASSES_ROOT, progid );
01450             }
01451         }
01452 
01453         uirow = MSI_CreateRecord( 1 );
01454         MSI_RecordSetStringW( uirow, 1, ext->Extension );
01455         msi_ui_actiondata( package, szUnregisterExtensionInfo, uirow );
01456         msiobj_release( &uirow->hdr );
01457     }
01458     return ERROR_SUCCESS;
01459 }
01460 
01461 UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
01462 {
01463     static const WCHAR szExtension[] = {'E','x','t','e','n','s','i','o','n',0};
01464     MSIRECORD *uirow;
01465     MSIMIME *mt;
01466     UINT r;
01467 
01468     r = load_classes_and_such( package );
01469     if (r != ERROR_SUCCESS)
01470         return r;
01471 
01472     LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
01473     {
01474         LPWSTR extension, key;
01475 
01476         /* 
01477          * check if the MIME is to be installed. Either as requested by an
01478          * extension or Class
01479          */
01480         mt->InstallMe = (mt->InstallMe ||
01481               (mt->Class && mt->Class->Installed) ||
01482               (mt->Extension && mt->Extension->Installed));
01483 
01484         if (!mt->InstallMe)
01485         {
01486             TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType));
01487             continue;
01488         }
01489 
01490         TRACE("Registering MIME type %s\n", debugstr_w(mt->ContentType));
01491 
01492         extension = msi_alloc( (strlenW( mt->Extension->Extension ) + 2) * sizeof(WCHAR) );
01493         key = msi_alloc( (strlenW( mt->ContentType ) + strlenW( szMIMEDatabase ) + 1) * sizeof(WCHAR) );
01494 
01495         if (extension && key)
01496         {
01497             extension[0] = '.';
01498             strcpyW( extension + 1, mt->Extension->Extension );
01499 
01500             strcpyW( key, szMIMEDatabase );
01501             strcatW( key, mt->ContentType );
01502             msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szExtension, extension );
01503 
01504             if (mt->clsid)
01505                 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szCLSID, mt->clsid );
01506         }
01507         msi_free( extension );
01508         msi_free( key );
01509 
01510         uirow = MSI_CreateRecord( 2 );
01511         MSI_RecordSetStringW( uirow, 1, mt->ContentType );
01512         MSI_RecordSetStringW( uirow, 2, mt->suffix );
01513         msi_ui_actiondata( package, szRegisterMIMEInfo, uirow );
01514         msiobj_release( &uirow->hdr );
01515     }
01516     return ERROR_SUCCESS;
01517 }
01518 
01519 UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
01520 {
01521     MSIRECORD *uirow;
01522     MSIMIME *mime;
01523     UINT r;
01524 
01525     r = load_classes_and_such( package );
01526     if (r != ERROR_SUCCESS)
01527         return r;
01528 
01529     LIST_FOR_EACH_ENTRY( mime, &package->mimes, MSIMIME, entry )
01530     {
01531         LONG res;
01532         LPWSTR mime_key;
01533 
01534         mime->InstallMe = (mime->InstallMe ||
01535                           (mime->Class && mime->Class->Installed) ||
01536                           (mime->Extension && mime->Extension->Installed));
01537 
01538         if (mime->InstallMe)
01539         {
01540             TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType));
01541             continue;
01542         }
01543 
01544         TRACE("Unregistering MIME type %s\n", debugstr_w(mime->ContentType));
01545 
01546         mime_key = msi_alloc( (strlenW( szMIMEDatabase ) + strlenW( mime->ContentType ) + 1) * sizeof(WCHAR) );
01547         if (mime_key)
01548         {
01549             strcpyW( mime_key, szMIMEDatabase );
01550             strcatW( mime_key, mime->ContentType );
01551             res = RegDeleteKeyW( HKEY_CLASSES_ROOT, mime_key );
01552             if (res != ERROR_SUCCESS)
01553                 WARN("Failed to delete MIME key %d\n", res);
01554             msi_free( mime_key );
01555         }
01556 
01557         uirow = MSI_CreateRecord( 2 );
01558         MSI_RecordSetStringW( uirow, 1, mime->ContentType );
01559         MSI_RecordSetStringW( uirow, 2, mime->suffix );
01560         msi_ui_actiondata( package, szUnregisterMIMEInfo, uirow );
01561         msiobj_release( &uirow->hdr );
01562     }
01563     return ERROR_SUCCESS;
01564 }

Generated on Sun May 27 2012 04:25:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.