Convert progids to a standard list.

This commit is contained in:
Mike McCormack 2005-09-06 09:26:18 +00:00 committed by Alexandre Julliard
parent d4f7f06f30
commit 1ceb25ba7b
5 changed files with 102 additions and 113 deletions

View File

@ -131,13 +131,15 @@ typedef struct tagMSIAPPID
BOOL RunAsInteractiveUser; BOOL RunAsInteractiveUser;
} MSIAPPID; } MSIAPPID;
typedef struct tagMSIPROGID MSIPROGID;
typedef struct tagMSICLASS typedef struct tagMSICLASS
{ {
struct list entry; struct list entry;
WCHAR CLSID[IDENTIFIER_SIZE]; /* Primary Key */ WCHAR CLSID[IDENTIFIER_SIZE]; /* Primary Key */
WCHAR Context[IDENTIFIER_SIZE]; /* Primary Key */ WCHAR Context[IDENTIFIER_SIZE]; /* Primary Key */
MSICOMPONENT *Component; MSICOMPONENT *Component;
INT ProgIDIndex; MSIPROGID *ProgID;
LPWSTR ProgIDText; LPWSTR ProgIDText;
LPWSTR Description; LPWSTR Description;
MSIAPPID *AppID; MSIAPPID *AppID;
@ -159,7 +161,7 @@ typedef struct tagMSIEXTENSION
struct list entry; struct list entry;
WCHAR Extension[256]; /* Primary Key */ WCHAR Extension[256]; /* Primary Key */
MSICOMPONENT *Component; MSICOMPONENT *Component;
INT ProgIDIndex; MSIPROGID *ProgID;
LPWSTR ProgIDText; LPWSTR ProgIDText;
MSIMIME *Mime; MSIMIME *Mime;
MSIFEATURE *Feature; MSIFEATURE *Feature;
@ -168,18 +170,19 @@ typedef struct tagMSIEXTENSION
struct list verbs; struct list verbs;
} MSIEXTENSION; } MSIEXTENSION;
typedef struct tagMSIPROGID struct tagMSIPROGID
{ {
struct list entry;
LPWSTR ProgID; /* Primary Key */ LPWSTR ProgID; /* Primary Key */
INT ParentIndex; MSIPROGID *Parent;
MSICLASS *Class; MSICLASS *Class;
LPWSTR Description; LPWSTR Description;
LPWSTR IconPath; LPWSTR IconPath;
/* not in the table, set during installation */ /* not in the table, set during installation */
BOOL InstallMe; BOOL InstallMe;
INT CurVerIndex; MSIPROGID *CurVer;
INT VersionIndIndex; MSIPROGID *VersionInd;
} MSIPROGID; };
typedef struct tagMSIVERB typedef struct tagMSIVERB
{ {

View File

@ -117,39 +117,36 @@ static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
return appid; return appid;
} }
static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid); static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid ); static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid );
static INT load_progid(MSIPACKAGE* package, MSIRECORD *row) static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
{ {
DWORD index = package->loaded_progids; MSIPROGID *progid;
LPCWSTR buffer; LPCWSTR buffer;
/* fill in the data */ /* fill in the data */
package->loaded_progids++; progid = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSIPROGID) );
if (package->loaded_progids == 1) if (!progid)
package->progids = HeapAlloc(GetProcessHeap(),0,sizeof(MSIPROGID)); return NULL;
else
package->progids = HeapReAlloc(GetProcessHeap(),0,
package->progids , package->loaded_progids * sizeof(MSIPROGID));
memset(&package->progids[index],0,sizeof(MSIPROGID)); list_add_tail( &package->progids, &progid->entry );
package->progids[index].ProgID = load_dynamic_stringW(row,1); progid->ProgID = load_dynamic_stringW(row,1);
TRACE("loading progid %s\n",debugstr_w(package->progids[index].ProgID)); TRACE("loading progid %s\n",debugstr_w(progid->ProgID));
buffer = MSI_RecordGetString(row,2); buffer = MSI_RecordGetString(row,2);
package->progids[index].ParentIndex = load_given_progid(package,buffer); progid->Parent = load_given_progid(package,buffer);
if (package->progids[index].ParentIndex < 0 && buffer) if (progid->Parent == NULL && buffer)
FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer)); FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
buffer = MSI_RecordGetString(row,3); buffer = MSI_RecordGetString(row,3);
package->progids[index].Class = load_given_class(package,buffer); progid->Class = load_given_class(package,buffer);
if (package->progids[index].Class == NULL && buffer) if (progid->Class == NULL && buffer)
FIXME("Unknown class %s\n",debugstr_w(buffer)); FIXME("Unknown class %s\n",debugstr_w(buffer));
package->progids[index].Description = load_dynamic_stringW(row,4); progid->Description = load_dynamic_stringW(row,4);
if (!MSI_RecordIsNull(row,6)) if (!MSI_RecordIsNull(row,6))
{ {
@ -160,11 +157,11 @@ static INT load_progid(MSIPACKAGE* package, MSIRECORD *row)
build_icon_path(package,FileName,&FilePath); build_icon_path(package,FileName,&FilePath);
package->progids[index].IconPath = progid->IconPath =
HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+10)* HeapAlloc(GetProcessHeap(),0,(strlenW(FilePath)+10)*
sizeof(WCHAR)); sizeof(WCHAR));
sprintfW(package->progids[index].IconPath,fmt,FilePath,icon_index); sprintfW(progid->IconPath,fmt,FilePath,icon_index);
HeapFree(GetProcessHeap(),0,FilePath); HeapFree(GetProcessHeap(),0,FilePath);
HeapFree(GetProcessHeap(),0,FileName); HeapFree(GetProcessHeap(),0,FileName);
@ -173,59 +170,59 @@ static INT load_progid(MSIPACKAGE* package, MSIRECORD *row)
{ {
buffer = MSI_RecordGetString(row,5); buffer = MSI_RecordGetString(row,5);
if (buffer) if (buffer)
build_icon_path(package,buffer,&(package->progids[index].IconPath)); build_icon_path(package,buffer,&(progid->IconPath));
} }
package->progids[index].CurVerIndex = -1; progid->CurVer = NULL;
package->progids[index].VersionIndIndex = -1; progid->VersionInd = NULL;
/* if we have a parent then we may be that parents CurVer */ /* if we have a parent then we may be that parents CurVer */
if (package->progids[index].ParentIndex >= 0 && if (progid->Parent && progid->Parent != progid)
package->progids[index].ParentIndex != index)
{ {
int pindex = package->progids[index].ParentIndex; MSIPROGID *parent = progid->Parent;
while (package->progids[pindex].ParentIndex>= 0 &&
package->progids[pindex].ParentIndex != pindex) while (parent->Parent && parent->Parent != progid)
pindex = package->progids[pindex].ParentIndex; parent = parent->Parent;
FIXME("BAD BAD need to determing if we are really the CurVer\n"); FIXME("BAD BAD need to determing if we are really the CurVer\n");
package->progids[index].CurVerIndex = pindex; progid->CurVer = parent;
package->progids[pindex].VersionIndIndex = index; progid->VersionInd = progid;
} }
return index; return progid;
} }
static INT load_given_progid(MSIPACKAGE *package, LPCWSTR progid) static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
{ {
INT rc; MSIPROGID *progid;
MSIRECORD *row; MSIRECORD *row;
INT i;
static const WCHAR ExecSeqQuery[] = static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', {'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','`',' ','W','H','E','R','E',' ',
'`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0}; '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
if (!progid) if (!name)
return -1; return NULL;
/* check for progids already loaded */ /* check for progids already loaded */
for (i = 0; i < package->loaded_progids; i++) LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
if (strcmpiW(package->progids[i].ProgID,progid)==0)
{ {
TRACE("found progid %s at index %i\n",debugstr_w(progid), i); if (strcmpiW( progid->ProgID,name )==0)
return i; {
TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
return progid;
}
} }
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, progid); row = MSI_QueryGetRecord( package->db, ExecSeqQuery, name );
if (!row) if (!row)
return -1; return NULL;
rc = load_progid(package, row); progid = load_progid(package, row);
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
return rc; return progid;
} }
static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row ) static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
@ -251,8 +248,7 @@ static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
cls->Component = get_loaded_component(package, buffer); cls->Component = get_loaded_component(package, buffer);
cls->ProgIDText = load_dynamic_stringW(row,4); cls->ProgIDText = load_dynamic_stringW(row,4);
cls->ProgIDIndex = cls->ProgID = load_given_progid(package, cls->ProgIDText);
load_given_progid(package, cls->ProgIDText);
cls->Description = load_dynamic_stringW(row,5); cls->Description = load_dynamic_stringW(row,5);
@ -452,7 +448,7 @@ static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
ext->Component = get_loaded_component( package,buffer ); ext->Component = get_loaded_component( package,buffer );
ext->ProgIDText = load_dynamic_stringW( row, 3 ); ext->ProgIDText = load_dynamic_stringW( row, 3 );
ext->ProgIDIndex = load_given_progid( package, ext->ProgIDText ); ext->ProgID = load_given_progid( package, ext->ProgIDText );
buffer = MSI_RecordGetString( row, 4 ); buffer = MSI_RecordGetString( row, 4 );
ext->Mime = load_given_mime( package, buffer ); ext->Mime = load_given_mime( package, buffer );
@ -717,7 +713,7 @@ static void load_classes_and_such(MSIPACKAGE *package)
if (!list_empty( &package->classes ) || if (!list_empty( &package->classes ) ||
!list_empty( &package->mimes ) || !list_empty( &package->mimes ) ||
!list_empty( &package->extensions ) || !list_empty( &package->extensions ) ||
package->progids ) !list_empty( &package->progids ) )
return; return;
load_all_classes(package); load_all_classes(package);
@ -728,25 +724,24 @@ static void load_classes_and_such(MSIPACKAGE *package)
load_all_mimes(package); load_all_mimes(package);
} }
static void mark_progid_for_install(MSIPACKAGE* package, INT index) static void mark_progid_for_install( MSIPACKAGE* package, MSIPROGID *progid )
{ {
MSIPROGID* progid; MSIPROGID *child;
int i;
if (index < 0 || index >= package->loaded_progids) if (!progid)
return; return;
progid = &package->progids[index];
if (progid->InstallMe == TRUE) if (progid->InstallMe == TRUE)
return; return;
progid->InstallMe = TRUE; progid->InstallMe = TRUE;
/* all children if this is a parent also install */ /* all children if this is a parent also install */
for (i = 0; i < package->loaded_progids; i++) LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry )
if (package->progids[i].ParentIndex == index) {
mark_progid_for_install(package,i); if (child->Parent == progid)
mark_progid_for_install( package, child );
}
} }
static void mark_mime_for_install( MSIMIME *mime ) static void mark_mime_for_install( MSIMIME *mime )
@ -902,8 +897,7 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
TRACE("Registering class %s (%p)\n", debugstr_w(cls->CLSID), cls); TRACE("Registering class %s (%p)\n", debugstr_w(cls->CLSID), cls);
cls->Installed = TRUE; cls->Installed = TRUE;
if (cls->ProgIDIndex >= 0) mark_progid_for_install( package, cls->ProgID );
mark_progid_for_install( package, cls->ProgIDIndex );
RegCreateKeyW( hkey, cls->CLSID, &hkey2 ); RegCreateKeyW( hkey, cls->CLSID, &hkey2 );
@ -975,12 +969,12 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
RegCloseKey(hkey3); RegCloseKey(hkey3);
if (cls->ProgIDIndex >= 0 || cls->ProgIDText) if (cls->ProgID || cls->ProgIDText)
{ {
LPCWSTR progid; LPCWSTR progid;
if (cls->ProgIDIndex >= 0) if (cls->ProgID)
progid = package->progids[cls->ProgIDIndex].ProgID; progid = cls->ProgID->ProgID;
else else
progid = cls->ProgIDText; progid = cls->ProgIDText;
@ -989,11 +983,9 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
(strlenW(progid)+1) *sizeof(WCHAR)); (strlenW(progid)+1) *sizeof(WCHAR));
RegCloseKey(hkey3); RegCloseKey(hkey3);
if (cls->ProgIDIndex >= 0 && if (cls->ProgID && cls->ProgID->VersionInd)
package->progids[cls->ProgIDIndex].VersionIndIndex >= 0)
{ {
LPWSTR viprogid = strdupW(package->progids[package->progids[ LPWSTR viprogid = strdupW( cls->ProgID->VersionInd->ProgID );
cls->ProgIDIndex].VersionIndIndex].ProgID);
RegCreateKeyW(hkey2,szVIProgID,&hkey3); RegCreateKeyW(hkey2,szVIProgID,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPBYTE)viprogid, RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPBYTE)viprogid,
(strlenW(viprogid)+1) *sizeof(WCHAR)); (strlenW(viprogid)+1) *sizeof(WCHAR));
@ -1144,7 +1136,7 @@ static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid,
{ {
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
if (progid->ParentIndex < 0) if (progid->Parent == NULL)
rc = register_progid_base(package, progid, clsid); rc = register_progid_base(package, progid, clsid);
else else
{ {
@ -1166,11 +1158,8 @@ static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid,
return rc; return rc;
} }
TRACE("Registering Parent %s index %i\n", TRACE("Registering Parent %s\n", debugstr_w(progid->Parent->ProgID) );
debugstr_w(package->progids[progid->ParentIndex].ProgID), rc = register_progid( package, progid->Parent, clsid );
progid->ParentIndex);
rc = register_progid(package,&package->progids[progid->ParentIndex],
clsid);
/* clsid is same as parent */ /* clsid is same as parent */
RegCreateKeyW(hkey,szCLSID,&hkey2); RegCreateKeyW(hkey,szCLSID,&hkey2);
@ -1195,13 +1184,11 @@ static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid,
} }
/* write out the current version */ /* write out the current version */
if (progid->CurVerIndex >= 0) if (progid->CurVer)
{ {
RegCreateKeyW(hkey,szCurVer,&hkey2); RegCreateKeyW(hkey,szCurVer,&hkey2);
RegSetValueExW(hkey2,NULL,0,REG_SZ, RegSetValueExW(hkey2,NULL,0,REG_SZ, (LPBYTE)progid->CurVer->ProgID,
(LPVOID)package->progids[progid->CurVerIndex].ProgID, (strlenW(progid->CurVer->ProgID)+1) * sizeof(WCHAR));
(strlenW(package->progids[progid->CurVerIndex].ProgID)+1) *
sizeof(WCHAR));
RegCloseKey(hkey2); RegCloseKey(hkey2);
} }
@ -1212,7 +1199,7 @@ static UINT register_progid(MSIPACKAGE *package, MSIPROGID* progid,
UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package) UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
{ {
INT i; MSIPROGID *progid;
MSIRECORD *uirow; MSIRECORD *uirow;
if (!package) if (!package)
@ -1220,29 +1207,27 @@ UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
load_classes_and_such(package); load_classes_and_such(package);
for (i = 0; i < package->loaded_progids; i++) LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
{ {
WCHAR clsid[0x1000]; WCHAR clsid[0x1000];
/* check if this progid is to be installed */ /* check if this progid is to be installed */
package->progids[i].InstallMe = ((package->progids[i].InstallMe) || if (progid->Class && progid->Class->Installed)
(package->progids[i].Class && progid->InstallMe = TRUE;
package->progids[i].Class->Installed));
if (!package->progids[i].InstallMe) if (!progid->InstallMe)
{ {
TRACE("progid %s not scheduled to be installed\n", TRACE("progid %s not scheduled to be installed\n",
debugstr_w(package->progids[i].ProgID)); debugstr_w(progid->ProgID));
continue; continue;
} }
TRACE("Registering progid %s index %i\n", TRACE("Registering progid %s\n", debugstr_w(progid->ProgID));
debugstr_w(package->progids[i].ProgID), i);
register_progid(package,&package->progids[i],clsid); register_progid( package, progid, clsid );
uirow = MSI_CreateRecord(1); uirow = MSI_CreateRecord(1);
MSI_RecordSetStringW(uirow,1,package->progids[i].ProgID); MSI_RecordSetStringW( uirow, 1, progid->ProgID );
ui_actiondata( package, szRegisterProgIdInfo, uirow ); ui_actiondata( package, szRegisterProgIdInfo, uirow );
msiobj_release( &uirow->hdr ); msiobj_release( &uirow->hdr );
} }
@ -1387,8 +1372,8 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
/* this is only registered if the extension has at least 1 verb /* this is only registered if the extension has at least 1 verb
* according to MSDN * according to MSDN
*/ */
if (ext->ProgIDIndex >= 0 && !list_empty( &ext->verbs ) ) if (ext->ProgID && !list_empty( &ext->verbs ) )
mark_progid_for_install(package, ext->ProgIDIndex); mark_progid_for_install( package, ext->ProgID );
mark_mime_for_install(ext->Mime); mark_mime_for_install(ext->Mime);
@ -1405,7 +1390,7 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
(strlenW(ext->Mime->ContentType)+1)*sizeof(WCHAR)); (strlenW(ext->Mime->ContentType)+1)*sizeof(WCHAR));
} }
if (ext->ProgIDIndex >= 0 || ext->ProgIDText) if (ext->ProgID || ext->ProgIDText)
{ {
static const WCHAR szSN[] = static const WCHAR szSN[] =
{'\\','S','h','e','l','l','N','e','w',0}; {'\\','S','h','e','l','l','N','e','w',0};
@ -1415,12 +1400,12 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
MSIVERB *verb; MSIVERB *verb;
INT Sequence = MSI_NULL_INTEGER; INT Sequence = MSI_NULL_INTEGER;
if (ext->ProgIDIndex >= 0) if (ext->ProgID)
progid = package->progids[ext->ProgIDIndex].ProgID; progid = ext->ProgID->ProgID;
else else
progid = ext->ProgIDText; progid = ext->ProgIDText;
RegSetValueExW(hkey,NULL,0,REG_SZ,(LPVOID)progid, RegSetValueExW( hkey, NULL, 0, REG_SZ, (LPBYTE)progid,
(strlenW(progid)+1)*sizeof(WCHAR)); (strlenW(progid)+1)*sizeof(WCHAR));
newkey = HeapAlloc(GetProcessHeap(),0, newkey = HeapAlloc(GetProcessHeap(),0,

View File

@ -528,15 +528,16 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
free_extension( ext ); free_extension( ext );
} }
for (i = 0; i < package->loaded_progids; i++) LIST_FOR_EACH_SAFE( item, cursor, &package->progids )
{ {
HeapFree(GetProcessHeap(),0,package->progids[i].ProgID); MSIPROGID *progid = LIST_ENTRY( item, MSIPROGID, entry );
HeapFree(GetProcessHeap(),0,package->progids[i].Description);
HeapFree(GetProcessHeap(),0,package->progids[i].IconPath);
}
if (package->progids && package->loaded_progids > 0) list_remove( &progid->entry );
HeapFree(GetProcessHeap(),0,package->progids); HeapFree( GetProcessHeap(), 0, progid->ProgID );
HeapFree( GetProcessHeap(), 0, progid->Description );
HeapFree( GetProcessHeap(), 0, progid->IconPath );
HeapFree( GetProcessHeap(), 0, progid );
}
LIST_FOR_EACH_SAFE( item, cursor, &package->mimes ) LIST_FOR_EACH_SAFE( item, cursor, &package->mimes )
{ {

View File

@ -194,8 +194,7 @@ typedef struct tagMSIPACKAGE
struct list classes; struct list classes;
struct list extensions; struct list extensions;
struct tagMSIPROGID *progids; struct list progids;
UINT loaded_progids;
struct list mimes; struct list mimes;
struct list appids; struct list appids;

View File

@ -390,6 +390,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
list_init( &package->classes ); list_init( &package->classes );
list_init( &package->mimes ); list_init( &package->mimes );
list_init( &package->extensions ); list_init( &package->extensions );
list_init( &package->progids );
/* OK, here is where we do a slew of things to the database to /* OK, here is where we do a slew of things to the database to
* prep for all that is to come as a package */ * prep for all that is to come as a package */