2006-02-17 00:04:10 +00:00
|
|
|
/*
|
|
|
|
* 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
|
2006-08-01 23:12:11 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
/* Actions handled in this module:
|
|
|
|
*
|
2006-02-17 00:04:10 +00:00
|
|
|
* RegisterClassInfo
|
|
|
|
* RegisterProgIdInfo
|
|
|
|
* RegisterExtensionInfo
|
|
|
|
* RegisterMIMEInfo
|
2010-05-29 08:55:43 +00:00
|
|
|
* UnregisterClassInfo
|
|
|
|
* UnregisterProgIdInfo
|
|
|
|
* UnregisterExtensionInfo
|
|
|
|
* UnregisterMIMEInfo
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
|
|
|
|
2018-03-04 23:30:58 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winerror.h"
|
|
|
|
#include "winreg.h"
|
|
|
|
#include "wine/debug.h"
|
2006-02-17 00:04:10 +00:00
|
|
|
#include "msipriv.h"
|
2018-03-04 23:30:58 +00:00
|
|
|
#include "winuser.h"
|
|
|
|
#include "wine/unicode.h"
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|
|
|
|
|
|
|
static MSIAPPID *load_appid( MSIPACKAGE* package, MSIRECORD *row )
|
|
|
|
{
|
|
|
|
LPCWSTR buffer;
|
|
|
|
MSIAPPID *appid;
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
appid = msi_alloc_zero( sizeof(MSIAPPID) );
|
|
|
|
if (!appid)
|
|
|
|
return NULL;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
appid->AppID = msi_dup_record_field( row, 1 );
|
|
|
|
TRACE("loading appid %s\n", debugstr_w( appid->AppID ));
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,2);
|
|
|
|
deformat_string( package, buffer, &appid->RemoteServerName );
|
|
|
|
|
|
|
|
appid->LocalServer = msi_dup_record_field(row,3);
|
|
|
|
appid->ServiceParameters = msi_dup_record_field(row,4);
|
|
|
|
appid->DllSurrogate = msi_dup_record_field(row,5);
|
|
|
|
|
|
|
|
appid->ActivateAtStorage = !MSI_RecordIsNull(row,6);
|
|
|
|
appid->RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
|
|
|
|
|
|
|
|
list_add_tail( &package->appids, &appid->entry );
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
return appid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIRECORD *row;
|
|
|
|
MSIAPPID *appid;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* check for appids already loaded */
|
|
|
|
LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (!strcmpiW( appid->AppID, name ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
TRACE("found appid %s %p\n", debugstr_w(name), appid);
|
|
|
|
return appid;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
row = MSI_QueryGetRecord(package->db, query, name);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!row)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
appid = load_appid(package, row);
|
|
|
|
msiobj_release(&row->hdr);
|
|
|
|
return appid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
|
|
|
|
static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid );
|
|
|
|
|
|
|
|
static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
|
|
|
|
{
|
|
|
|
MSIPROGID *progid;
|
|
|
|
LPCWSTR buffer;
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
progid = msi_alloc_zero( sizeof(MSIPROGID) );
|
|
|
|
if (!progid)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
list_add_tail( &package->progids, &progid->entry );
|
|
|
|
|
|
|
|
progid->ProgID = msi_dup_record_field(row,1);
|
|
|
|
TRACE("loading progid %s\n",debugstr_w(progid->ProgID));
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,2);
|
|
|
|
progid->Parent = load_given_progid(package,buffer);
|
|
|
|
if (progid->Parent == NULL && buffer)
|
|
|
|
FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,3);
|
|
|
|
progid->Class = load_given_class(package,buffer);
|
|
|
|
if (progid->Class == NULL && buffer)
|
|
|
|
FIXME("Unknown class %s\n",debugstr_w(buffer));
|
|
|
|
|
|
|
|
progid->Description = msi_dup_record_field(row,4);
|
|
|
|
|
|
|
|
if (!MSI_RecordIsNull(row,6))
|
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
INT icon_index = MSI_RecordGetInteger(row,6);
|
2006-02-17 00:04:10 +00:00
|
|
|
LPCWSTR FileName = MSI_RecordGetString(row,5);
|
|
|
|
LPWSTR FilePath;
|
|
|
|
static const WCHAR fmt[] = {'%','s',',','%','i',0};
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
FilePath = msi_build_icon_path(package, FileName);
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
progid->IconPath = msi_alloc( (strlenW(FilePath)+10)* sizeof(WCHAR) );
|
|
|
|
|
|
|
|
sprintfW(progid->IconPath,fmt,FilePath,icon_index);
|
|
|
|
|
|
|
|
msi_free(FilePath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer = MSI_RecordGetString(row,5);
|
|
|
|
if (buffer)
|
2012-01-21 17:19:12 +00:00
|
|
|
progid->IconPath = msi_build_icon_path(package, buffer);
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
progid->CurVer = NULL;
|
|
|
|
progid->VersionInd = NULL;
|
|
|
|
|
|
|
|
/* if we have a parent then we may be that parents CurVer */
|
|
|
|
if (progid->Parent && progid->Parent != progid)
|
|
|
|
{
|
|
|
|
MSIPROGID *parent = progid->Parent;
|
|
|
|
|
|
|
|
while (parent->Parent && parent->Parent != parent)
|
|
|
|
parent = parent->Parent;
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
/* FIXME: need to determine if we are really the CurVer */
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
progid->CurVer = parent;
|
|
|
|
parent->VersionInd = progid;
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
return progid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIPROGID *progid;
|
|
|
|
MSIRECORD *row;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* check for progids already loaded */
|
|
|
|
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (!strcmpiW( progid->ProgID, name ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
|
|
|
|
return progid;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
row = MSI_QueryGetRecord( package->db, query, name );
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!row)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
progid = load_progid(package, row);
|
|
|
|
msiobj_release(&row->hdr);
|
|
|
|
return progid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
|
|
|
|
{
|
|
|
|
MSICLASS *cls;
|
|
|
|
DWORD i;
|
|
|
|
LPCWSTR buffer;
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
cls = msi_alloc_zero( sizeof(MSICLASS) );
|
|
|
|
if (!cls)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
list_add_tail( &package->classes, &cls->entry );
|
|
|
|
|
|
|
|
cls->clsid = msi_dup_record_field( row, 1 );
|
|
|
|
TRACE("loading class %s\n",debugstr_w(cls->clsid));
|
|
|
|
cls->Context = msi_dup_record_field( row, 2 );
|
|
|
|
buffer = MSI_RecordGetString(row,3);
|
2012-01-21 17:19:12 +00:00
|
|
|
cls->Component = msi_get_loaded_component( package, buffer );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
cls->ProgIDText = msi_dup_record_field(row,4);
|
|
|
|
cls->ProgID = load_given_progid(package, cls->ProgIDText);
|
|
|
|
|
|
|
|
cls->Description = msi_dup_record_field(row,5);
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,6);
|
|
|
|
if (buffer)
|
|
|
|
cls->AppID = load_given_appid(package, buffer);
|
|
|
|
|
|
|
|
cls->FileTypeMask = msi_dup_record_field(row,7);
|
|
|
|
|
|
|
|
if (!MSI_RecordIsNull(row,9))
|
|
|
|
{
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
INT icon_index = MSI_RecordGetInteger(row,9);
|
2006-02-17 00:04:10 +00:00
|
|
|
LPCWSTR FileName = MSI_RecordGetString(row,8);
|
|
|
|
LPWSTR FilePath;
|
|
|
|
static const WCHAR fmt[] = {'%','s',',','%','i',0};
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
FilePath = msi_build_icon_path(package, FileName);
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
cls->IconPath = msi_alloc( (strlenW(FilePath)+5)* sizeof(WCHAR) );
|
|
|
|
|
|
|
|
sprintfW(cls->IconPath,fmt,FilePath,icon_index);
|
|
|
|
|
|
|
|
msi_free(FilePath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer = MSI_RecordGetString(row,8);
|
|
|
|
if (buffer)
|
2012-01-21 17:19:12 +00:00
|
|
|
cls->IconPath = msi_build_icon_path(package, buffer);
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
|
|
|
cls->DefInprocHandler = strdupW(ole2);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
cls->DefInprocHandler32 = strdupW(ole32);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
cls->DefInprocHandler = strdupW(ole2);
|
|
|
|
cls->DefInprocHandler32 = strdupW(ole32);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
cls->DefInprocHandler32 = msi_dup_record_field( row, 10 );
|
|
|
|
msi_reduce_to_long_filename( cls->DefInprocHandler32 );
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer = MSI_RecordGetString(row,11);
|
|
|
|
deformat_string(package,buffer,&cls->Argument);
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,12);
|
2012-01-21 17:19:12 +00:00
|
|
|
cls->Feature = msi_get_loaded_feature(package, buffer);
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
cls->Attributes = MSI_RecordGetInteger(row,13);
|
2014-04-23 14:48:52 +00:00
|
|
|
cls->action = INSTALLSTATE_UNKNOWN;
|
2006-02-17 00:04:10 +00:00
|
|
|
return cls;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-01-16 10:11:22 +00:00
|
|
|
* the Class table has 3 primary keys. Generally it is only
|
2006-02-17 00:04:10 +00:00
|
|
|
* referenced through the first CLSID key. However when loading
|
|
|
|
* all of the classes we need to make sure we do not ignore rows
|
2008-01-16 10:11:22 +00:00
|
|
|
* with other Context and ComponentIndexs
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
|
|
|
static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSICLASS *cls;
|
|
|
|
MSIRECORD *row;
|
|
|
|
|
|
|
|
if (!classid)
|
|
|
|
return NULL;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
/* check for classes already loaded */
|
|
|
|
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (!strcmpiW( cls->clsid, classid ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
|
|
|
|
return cls;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
row = MSI_QueryGetRecord(package->db, query, classid);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!row)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cls = load_class(package, row);
|
|
|
|
msiobj_release(&row->hdr);
|
|
|
|
return cls;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR extension );
|
|
|
|
|
|
|
|
static MSIMIME *load_mime( MSIPACKAGE* package, MSIRECORD *row )
|
|
|
|
{
|
2010-05-29 08:55:43 +00:00
|
|
|
LPCWSTR extension;
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIMIME *mt;
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
mt = msi_alloc_zero( sizeof(MSIMIME) );
|
|
|
|
if (!mt)
|
|
|
|
return mt;
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
mt->ContentType = msi_dup_record_field( row, 1 );
|
2006-02-17 00:04:10 +00:00
|
|
|
TRACE("loading mime %s\n", debugstr_w(mt->ContentType));
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
extension = MSI_RecordGetString( row, 2 );
|
|
|
|
mt->Extension = load_given_extension( package, extension );
|
|
|
|
mt->suffix = strdupW( extension );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
mt->clsid = msi_dup_record_field( row, 3 );
|
|
|
|
mt->Class = load_given_class( package, mt->clsid );
|
|
|
|
|
|
|
|
list_add_tail( &package->mimes, &mt->entry );
|
|
|
|
|
|
|
|
return mt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIRECORD *row;
|
|
|
|
MSIMIME *mt;
|
|
|
|
|
|
|
|
if (!mime)
|
|
|
|
return NULL;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
/* check for mime already loaded */
|
|
|
|
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (!strcmpiW( mt->ContentType, mime ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
|
|
|
|
return mt;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
row = MSI_QueryGetRecord(package->db, query, mime);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!row)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mt = load_mime(package, row);
|
|
|
|
msiobj_release(&row->hdr);
|
|
|
|
return mt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
|
|
|
|
{
|
|
|
|
MSIEXTENSION *ext;
|
|
|
|
LPCWSTR buffer;
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
ext = msi_alloc_zero( sizeof(MSIEXTENSION) );
|
|
|
|
if (!ext)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
list_init( &ext->verbs );
|
|
|
|
|
|
|
|
list_add_tail( &package->extensions, &ext->entry );
|
|
|
|
|
|
|
|
ext->Extension = msi_dup_record_field( row, 1 );
|
|
|
|
TRACE("loading extension %s\n", debugstr_w(ext->Extension));
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString( row, 2 );
|
2012-01-21 17:19:12 +00:00
|
|
|
ext->Component = msi_get_loaded_component( package, buffer );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
ext->ProgIDText = msi_dup_record_field( row, 3 );
|
|
|
|
ext->ProgID = load_given_progid( package, ext->ProgIDText );
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString( row, 4 );
|
|
|
|
ext->Mime = load_given_mime( package, buffer );
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,5);
|
2012-01-21 17:19:12 +00:00
|
|
|
ext->Feature = msi_get_loaded_feature( package, buffer );
|
2014-04-23 14:48:52 +00:00
|
|
|
ext->action = INSTALLSTATE_UNKNOWN;
|
2006-02-17 00:04:10 +00:00
|
|
|
return ext;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* While the extension table has 2 primary keys, this function is only looking
|
2008-01-16 10:11:22 +00:00
|
|
|
* at the Extension key which is what is referenced as a foreign key
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
|
|
|
static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIEXTENSION *ext;
|
2012-01-21 17:19:12 +00:00
|
|
|
MSIRECORD *row;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
|
2008-12-27 15:10:14 +00:00
|
|
|
if (name[0] == '.')
|
|
|
|
name++;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
/* check for extensions already loaded */
|
|
|
|
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (!strcmpiW( ext->Extension, name ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
|
|
|
|
return ext;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
row = MSI_QueryGetRecord( package->db, query, name );
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!row)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ext = load_extension(package, row);
|
|
|
|
msiobj_release(&row->hdr);
|
|
|
|
return ext;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
|
|
|
|
{
|
2009-01-18 12:52:01 +00:00
|
|
|
MSIPACKAGE* package = param;
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIVERB *verb;
|
|
|
|
LPCWSTR buffer;
|
|
|
|
MSIEXTENSION *extension;
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,1);
|
|
|
|
extension = load_given_extension( package, buffer );
|
|
|
|
if (!extension)
|
|
|
|
{
|
|
|
|
ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fill in the data */
|
|
|
|
|
|
|
|
verb = msi_alloc_zero( sizeof(MSIVERB) );
|
|
|
|
if (!verb)
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
|
|
|
verb->Verb = msi_dup_record_field(row,2);
|
|
|
|
TRACE("loading verb %s\n",debugstr_w(verb->Verb));
|
|
|
|
verb->Sequence = MSI_RecordGetInteger(row,3);
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,4);
|
|
|
|
deformat_string(package,buffer,&verb->Command);
|
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(row,5);
|
|
|
|
deformat_string(package,buffer,&verb->Argument);
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
/* associate the verb with the correct extension */
|
2006-02-17 00:04:10 +00:00
|
|
|
list_add_tail( &extension->verbs, &verb->entry );
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
|
|
|
|
{
|
|
|
|
MSICOMPONENT *comp;
|
|
|
|
LPCWSTR clsid;
|
|
|
|
LPCWSTR context;
|
|
|
|
LPCWSTR buffer;
|
2009-01-18 12:52:01 +00:00
|
|
|
MSIPACKAGE* package = param;
|
2006-02-17 00:04:10 +00:00
|
|
|
MSICLASS *cls;
|
|
|
|
BOOL match = FALSE;
|
|
|
|
|
|
|
|
clsid = MSI_RecordGetString(rec,1);
|
|
|
|
context = MSI_RecordGetString(rec,2);
|
|
|
|
buffer = MSI_RecordGetString(rec,3);
|
2012-01-21 17:19:12 +00:00
|
|
|
comp = msi_get_loaded_component(package, buffer);
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
|
|
|
{
|
|
|
|
if (strcmpiW( clsid, cls->clsid ))
|
|
|
|
continue;
|
|
|
|
if (strcmpW( context, cls->Context ))
|
|
|
|
continue;
|
|
|
|
if (comp == cls->Component)
|
|
|
|
{
|
|
|
|
match = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!match)
|
|
|
|
load_class(package, rec);
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_all_classes( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ','`','C','l','a','s','s','`',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIQUERY *view;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (rc != ERROR_SUCCESS)
|
2012-01-21 17:19:12 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
|
|
|
|
msiobj_release(&view->hdr);
|
2012-01-21 17:19:12 +00:00
|
|
|
return rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
|
|
|
|
{
|
|
|
|
MSICOMPONENT *comp;
|
|
|
|
LPCWSTR buffer;
|
|
|
|
LPCWSTR extension;
|
2009-01-18 12:52:01 +00:00
|
|
|
MSIPACKAGE* package = param;
|
2006-02-17 00:04:10 +00:00
|
|
|
BOOL match = FALSE;
|
|
|
|
MSIEXTENSION *ext;
|
|
|
|
|
|
|
|
extension = MSI_RecordGetString(rec,1);
|
|
|
|
buffer = MSI_RecordGetString(rec,2);
|
2012-01-21 17:19:12 +00:00
|
|
|
comp = msi_get_loaded_component(package, buffer);
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
2011-03-20 08:47:41 +00:00
|
|
|
if (strcmpiW(extension, ext->Extension))
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
if (comp == ext->Component)
|
|
|
|
{
|
|
|
|
match = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!match)
|
|
|
|
load_extension(package, rec);
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_all_extensions( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','E','x','t','e','n','s','i','o','n','`',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIQUERY *view;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
rc = MSI_DatabaseOpenViewW( package->db, query, &view );
|
2006-02-17 00:04:10 +00:00
|
|
|
if (rc != ERROR_SUCCESS)
|
2012-01-21 17:19:12 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
|
|
|
|
msiobj_release(&view->hdr);
|
2012-01-21 17:19:12 +00:00
|
|
|
return rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
|
|
|
|
{
|
|
|
|
LPCWSTR buffer;
|
2009-01-18 12:52:01 +00:00
|
|
|
MSIPACKAGE* package = param;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(rec,1);
|
|
|
|
load_given_progid(package,buffer);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_all_progids( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ','F','R','O','M',' ',
|
|
|
|
'`','P','r','o','g','I','d','`',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIQUERY *view;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (rc != ERROR_SUCCESS)
|
2012-01-21 17:19:12 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
|
|
|
|
msiobj_release(&view->hdr);
|
2012-01-21 17:19:12 +00:00
|
|
|
return rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_all_verbs( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','V','e','r','b','`',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIQUERY *view;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (rc != ERROR_SUCCESS)
|
2012-01-21 17:19:12 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
|
|
|
|
msiobj_release(&view->hdr);
|
2012-01-21 17:19:12 +00:00
|
|
|
return rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
|
|
|
|
{
|
|
|
|
LPCWSTR buffer;
|
2009-01-18 12:52:01 +00:00
|
|
|
MSIPACKAGE* package = param;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
buffer = MSI_RecordGetString(rec,1);
|
|
|
|
load_given_mime(package,buffer);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_all_mimes( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR query[] = {
|
|
|
|
'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};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIQUERY *view;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
rc = MSI_DatabaseOpenViewW(package->db, query, &view);
|
2006-02-17 00:04:10 +00:00
|
|
|
if (rc != ERROR_SUCCESS)
|
2012-01-21 17:19:12 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
|
|
|
|
msiobj_release(&view->hdr);
|
2012-01-21 17:19:12 +00:00
|
|
|
return rc;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
static UINT load_classes_and_such( MSIPACKAGE *package )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
TRACE("Loading all the class info and related tables\n");
|
|
|
|
|
|
|
|
/* check if already loaded */
|
|
|
|
if (!list_empty( &package->classes ) ||
|
|
|
|
!list_empty( &package->mimes ) ||
|
|
|
|
!list_empty( &package->extensions ) ||
|
2012-01-21 17:19:12 +00:00
|
|
|
!list_empty( &package->progids )) return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
r = load_all_classes( package );
|
|
|
|
if (r != ERROR_SUCCESS) return r;
|
|
|
|
|
|
|
|
r = load_all_extensions( package );
|
|
|
|
if (r != ERROR_SUCCESS) return r;
|
|
|
|
|
|
|
|
r = load_all_progids( package );
|
|
|
|
if (r != ERROR_SUCCESS) return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
/* these loads must come after the other loads */
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_all_verbs( package );
|
|
|
|
if (r != ERROR_SUCCESS) return r;
|
|
|
|
|
|
|
|
return load_all_mimes( package );
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
static const WCHAR szRemoteServerName[] =
|
|
|
|
{'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0};
|
|
|
|
static const WCHAR szLocalService[] =
|
|
|
|
{'L','o','c','a','l','S','e','r','v','i','c','e',0};
|
|
|
|
static const WCHAR szService[] =
|
|
|
|
{'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0};
|
|
|
|
static const WCHAR szDLL[] =
|
|
|
|
{'D','l','l','S','u','r','r','o','g','a','t','e',0};
|
|
|
|
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};
|
|
|
|
static const WCHAR szRunAs[] = {'R','u','n','A','s',0};
|
2008-01-16 10:11:22 +00:00
|
|
|
static const WCHAR szUser[] =
|
2006-02-17 00:04:10 +00:00
|
|
|
{'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0};
|
|
|
|
|
|
|
|
HKEY hkey2,hkey3;
|
|
|
|
|
|
|
|
RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2);
|
|
|
|
RegCreateKeyW( hkey2, appid->AppID, &hkey3 );
|
|
|
|
RegCloseKey(hkey2);
|
|
|
|
msi_reg_set_val_str( hkey3, NULL, app );
|
|
|
|
|
|
|
|
if (appid->RemoteServerName)
|
|
|
|
msi_reg_set_val_str( hkey3, szRemoteServerName, appid->RemoteServerName );
|
|
|
|
|
|
|
|
if (appid->LocalServer)
|
|
|
|
msi_reg_set_val_str( hkey3, szLocalService, appid->LocalServer );
|
|
|
|
|
|
|
|
if (appid->ServiceParameters)
|
|
|
|
msi_reg_set_val_str( hkey3, szService, appid->ServiceParameters );
|
|
|
|
|
|
|
|
if (appid->DllSurrogate)
|
|
|
|
msi_reg_set_val_str( hkey3, szDLL, appid->DllSurrogate );
|
|
|
|
|
|
|
|
if (appid->ActivateAtStorage)
|
|
|
|
msi_reg_set_val_str( hkey3, szActivate, szY );
|
|
|
|
|
|
|
|
if (appid->RunAsInteractiveUser)
|
|
|
|
msi_reg_set_val_str( hkey3, szRunAs, szUser );
|
|
|
|
|
|
|
|
RegCloseKey(hkey3);
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
|
|
|
|
{
|
|
|
|
static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
|
2010-10-22 13:18:11 +00:00
|
|
|
const WCHAR *keypath;
|
2010-05-29 08:55:43 +00:00
|
|
|
MSIRECORD *uirow;
|
2012-01-21 17:19:12 +00:00
|
|
|
HKEY hkey, hkey2, hkey3;
|
2006-02-17 00:04:10 +00:00
|
|
|
MSICLASS *cls;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2010-10-22 13:18:11 +00:00
|
|
|
|
|
|
|
if (is_64bit && package->platform == PLATFORM_INTEL)
|
|
|
|
keypath = szWow6432NodeCLSID;
|
|
|
|
else
|
|
|
|
keypath = szCLSID;
|
|
|
|
|
|
|
|
if (RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, &hkey) != ERROR_SUCCESS)
|
2006-02-17 00:04:10 +00:00
|
|
|
return ERROR_FUNCTION_FAILED;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
|
|
|
{
|
|
|
|
MSICOMPONENT *comp;
|
|
|
|
MSIFILE *file;
|
2006-08-30 19:24:26 +00:00
|
|
|
DWORD size;
|
2006-02-17 00:04:10 +00:00
|
|
|
LPWSTR argument;
|
|
|
|
MSIFEATURE *feature;
|
|
|
|
|
|
|
|
comp = cls->Component;
|
|
|
|
if ( !comp )
|
|
|
|
continue;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (!comp->Enabled)
|
|
|
|
{
|
|
|
|
TRACE("component is disabled\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
feature = cls->Feature;
|
2010-03-01 12:01:30 +00:00
|
|
|
if (!feature)
|
|
|
|
continue;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
feature->Action = msi_get_feature_action( package, feature );
|
|
|
|
if (feature->Action != INSTALLSTATE_LOCAL &&
|
|
|
|
feature->Action != INSTALLSTATE_ADVERTISED )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
TRACE("feature %s not scheduled for installation, skipping registration of class %s\n",
|
2010-03-01 12:01:30 +00:00
|
|
|
debugstr_w(feature->Feature), debugstr_w(cls->clsid));
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
if (!comp->KeyPath || !(file = msi_get_loaded_file( package, comp->KeyPath )))
|
2010-05-29 08:55:43 +00:00
|
|
|
{
|
|
|
|
TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
|
|
|
|
continue;
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls);
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
cls->action = INSTALLSTATE_LOCAL;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
RegCreateKeyW( hkey, cls->clsid, &hkey2 );
|
|
|
|
|
|
|
|
if (cls->Description)
|
|
|
|
msi_reg_set_val_str( hkey2, NULL, cls->Description );
|
|
|
|
|
|
|
|
RegCreateKeyW( hkey2, cls->Context, &hkey3 );
|
|
|
|
|
2006-08-30 19:24:26 +00:00
|
|
|
/*
|
|
|
|
* FIXME: Implement install on demand (advertised components).
|
|
|
|
*
|
|
|
|
* ole32.dll should call msi.MsiProvideComponentFromDescriptor()
|
|
|
|
* when it needs an InProcServer that doesn't exist.
|
|
|
|
* The component advertise string should be in the "InProcServer" value.
|
2006-02-17 00:04:10 +00:00
|
|
|
*/
|
2006-08-30 19:24:26 +00:00
|
|
|
size = lstrlenW( file->TargetPath )+1;
|
|
|
|
if (cls->Argument)
|
|
|
|
size += lstrlenW(cls->Argument)+1;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2006-08-30 19:24:26 +00:00
|
|
|
argument = msi_alloc( size * sizeof(WCHAR) );
|
|
|
|
lstrcpyW( argument, file->TargetPath );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2006-08-30 19:24:26 +00:00
|
|
|
if (cls->Argument)
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2006-08-30 19:24:26 +00:00
|
|
|
lstrcatW( argument, szSpace );
|
|
|
|
lstrcatW( argument, cls->Argument );
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-30 19:24:26 +00:00
|
|
|
msi_reg_set_val_str( hkey3, NULL, argument );
|
|
|
|
msi_free(argument);
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
RegCloseKey(hkey3);
|
|
|
|
|
|
|
|
if (cls->ProgID || cls->ProgIDText)
|
|
|
|
{
|
|
|
|
LPCWSTR progid;
|
|
|
|
|
|
|
|
if (cls->ProgID)
|
|
|
|
progid = cls->ProgID->ProgID;
|
|
|
|
else
|
|
|
|
progid = cls->ProgIDText;
|
|
|
|
|
|
|
|
msi_reg_set_subkey_val( hkey2, szProgID, NULL, progid );
|
|
|
|
|
|
|
|
if (cls->ProgID && cls->ProgID->VersionInd)
|
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
msi_reg_set_subkey_val( hkey2, szVIProgID, NULL,
|
2006-02-17 00:04:10 +00:00
|
|
|
cls->ProgID->VersionInd->ProgID );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cls->AppID)
|
2006-08-30 19:24:26 +00:00
|
|
|
{
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIAPPID *appid = cls->AppID;
|
|
|
|
msi_reg_set_val_str( hkey2, szAppID, appid->AppID );
|
|
|
|
register_appid( appid, cls->Description );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cls->IconPath)
|
|
|
|
msi_reg_set_subkey_val( hkey2, szDefaultIcon, NULL, cls->IconPath );
|
|
|
|
|
|
|
|
if (cls->DefInprocHandler)
|
2010-05-29 08:55:43 +00:00
|
|
|
msi_reg_set_subkey_val( hkey2, szInprocHandler, NULL, cls->DefInprocHandler );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if (cls->DefInprocHandler32)
|
2010-05-29 08:55:43 +00:00
|
|
|
msi_reg_set_subkey_val( hkey2, szInprocHandler32, NULL, cls->DefInprocHandler32 );
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
RegCloseKey(hkey2);
|
|
|
|
|
|
|
|
/* if there is a FileTypeMask, register the FileType */
|
|
|
|
if (cls->FileTypeMask)
|
|
|
|
{
|
|
|
|
LPWSTR ptr, ptr2;
|
|
|
|
LPWSTR keyname;
|
|
|
|
INT index = 0;
|
|
|
|
ptr = cls->FileTypeMask;
|
|
|
|
while (ptr && *ptr)
|
|
|
|
{
|
|
|
|
ptr2 = strchrW(ptr,';');
|
|
|
|
if (ptr2)
|
|
|
|
*ptr2 = 0;
|
|
|
|
keyname = msi_alloc( (strlenW(szFileType_fmt) + strlenW(cls->clsid) + 4) * sizeof(WCHAR));
|
|
|
|
sprintfW( keyname, szFileType_fmt, cls->clsid, index );
|
|
|
|
|
|
|
|
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, ptr );
|
|
|
|
msi_free(keyname);
|
|
|
|
|
|
|
|
if (ptr2)
|
|
|
|
ptr = ptr2+1;
|
|
|
|
else
|
|
|
|
ptr = NULL;
|
|
|
|
|
|
|
|
index ++;
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
uirow = MSI_CreateRecord(1);
|
|
|
|
MSI_RecordSetStringW( uirow, 1, cls->clsid );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release(&uirow->hdr);
|
|
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
2010-05-29 08:55:43 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
|
|
|
|
{
|
|
|
|
static const WCHAR szFileType[] = {'F','i','l','e','T','y','p','e','\\',0};
|
2010-10-22 13:18:11 +00:00
|
|
|
const WCHAR *keypath;
|
2010-05-29 08:55:43 +00:00
|
|
|
MSIRECORD *uirow;
|
|
|
|
MSICLASS *cls;
|
|
|
|
HKEY hkey, hkey2;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2010-10-22 13:18:11 +00:00
|
|
|
|
|
|
|
if (is_64bit && package->platform == PLATFORM_INTEL)
|
|
|
|
keypath = szWow6432NodeCLSID;
|
|
|
|
else
|
|
|
|
keypath = szCLSID;
|
|
|
|
|
|
|
|
if (RegOpenKeyW( HKEY_CLASSES_ROOT, keypath, &hkey ) != ERROR_SUCCESS)
|
2010-05-29 08:55:43 +00:00
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
|
|
|
|
{
|
|
|
|
MSIFEATURE *feature;
|
|
|
|
MSICOMPONENT *comp;
|
|
|
|
LPWSTR filetype;
|
|
|
|
LONG res;
|
|
|
|
|
|
|
|
comp = cls->Component;
|
|
|
|
if (!comp)
|
|
|
|
continue;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (!comp->Enabled)
|
|
|
|
{
|
|
|
|
TRACE("component is disabled\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
feature = cls->Feature;
|
|
|
|
if (!feature)
|
|
|
|
continue;
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
feature->Action = msi_get_feature_action( package, feature );
|
|
|
|
if (feature->Action != INSTALLSTATE_ABSENT)
|
2010-05-29 08:55:43 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
TRACE("feature %s not scheduled for removal, skipping unregistration of class %s\n",
|
2010-05-29 08:55:43 +00:00
|
|
|
debugstr_w(feature->Feature), debugstr_w(cls->clsid));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls);
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
cls->action = INSTALLSTATE_ABSENT;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2015-11-21 16:44:38 +00:00
|
|
|
res = RegDeleteTreeW( hkey, cls->clsid );
|
2010-05-29 08:55:43 +00:00
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete class key %d\n", res);
|
|
|
|
|
|
|
|
if (cls->AppID)
|
|
|
|
{
|
|
|
|
res = RegOpenKeyW( HKEY_CLASSES_ROOT, szAppID, &hkey2 );
|
|
|
|
if (res == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
res = RegDeleteKeyW( hkey2, cls->AppID->AppID );
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete appid key %d\n", res);
|
|
|
|
RegCloseKey( hkey2 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cls->FileTypeMask)
|
|
|
|
{
|
|
|
|
filetype = msi_alloc( (strlenW( szFileType ) + strlenW( cls->clsid ) + 1) * sizeof(WCHAR) );
|
|
|
|
if (filetype)
|
|
|
|
{
|
|
|
|
strcpyW( filetype, szFileType );
|
|
|
|
strcatW( filetype, cls->clsid );
|
2015-11-21 16:44:38 +00:00
|
|
|
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
|
2010-05-29 08:55:43 +00:00
|
|
|
msi_free( filetype );
|
|
|
|
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete file type %d\n", res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uirow = MSI_CreateRecord( 1 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, cls->clsid );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2010-05-29 08:55:43 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
return ERROR_SUCCESS;
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
static LPCWSTR get_clsid_of_progid( const MSIPROGID *progid )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
|
|
|
while (progid)
|
|
|
|
{
|
|
|
|
if (progid->Class)
|
|
|
|
return progid->Class->clsid;
|
2008-05-17 19:46:01 +00:00
|
|
|
if (progid->Parent == progid)
|
|
|
|
break;
|
2006-02-17 00:04:10 +00:00
|
|
|
progid = progid->Parent;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
static UINT register_progid( const MSIPROGID* progid )
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2010-05-29 08:55:43 +00:00
|
|
|
static const WCHAR szCurVer[] = {'C','u','r','V','e','r',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
HKEY hkey = 0;
|
|
|
|
UINT rc;
|
|
|
|
|
|
|
|
rc = RegCreateKeyW( HKEY_CLASSES_ROOT, progid->ProgID, &hkey );
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
LPCWSTR clsid = get_clsid_of_progid( progid );
|
|
|
|
|
|
|
|
if (clsid)
|
|
|
|
msi_reg_set_subkey_val( hkey, szCLSID, NULL, clsid );
|
|
|
|
else
|
2010-10-22 13:18:11 +00:00
|
|
|
TRACE("%s has no class\n", debugstr_w( progid->ProgID ) );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if (progid->Description)
|
|
|
|
msi_reg_set_val_str( hkey, NULL, progid->Description );
|
|
|
|
|
|
|
|
if (progid->IconPath)
|
|
|
|
msi_reg_set_subkey_val( hkey, szDefaultIcon, NULL, progid->IconPath );
|
|
|
|
|
|
|
|
/* write out the current version */
|
|
|
|
if (progid->CurVer)
|
|
|
|
msi_reg_set_subkey_val( hkey, szCurVer, NULL, progid->CurVer->ProgID );
|
|
|
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ERR("failed to create key %s\n", debugstr_w( progid->ProgID ) );
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
static const MSICLASS *get_progid_class( const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
while (progid)
|
|
|
|
{
|
|
|
|
if (progid->Parent) progid = progid->Parent;
|
|
|
|
if (progid->Class) return progid->Class;
|
|
|
|
if (!progid->Parent || progid->Parent == progid) break;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL has_class_installed( const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
const MSICLASS *class = get_progid_class( progid );
|
|
|
|
if (!class || !class->ProgID) return FALSE;
|
|
|
|
return (class->action == INSTALLSTATE_LOCAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL has_one_extension_installed( const MSIPACKAGE *package, const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
const MSIEXTENSION *extension;
|
|
|
|
LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
|
|
|
if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
|
|
|
|
extension->action == INSTALLSTATE_LOCAL) return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
|
|
|
|
{
|
|
|
|
MSIPROGID *progid;
|
|
|
|
MSIRECORD *uirow;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
|
|
|
|
{
|
2014-04-23 14:48:52 +00:00
|
|
|
if (!has_class_installed( progid ) && !has_one_extension_installed( package, progid ))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2014-04-23 14:48:52 +00:00
|
|
|
TRACE("progid %s not scheduled to be installed\n", debugstr_w(progid->ProgID));
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TRACE("Registering progid %s\n", debugstr_w(progid->ProgID));
|
|
|
|
|
|
|
|
register_progid( progid );
|
|
|
|
|
|
|
|
uirow = MSI_CreateRecord( 1 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, progid->ProgID );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
static BOOL has_class_removed( const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
const MSICLASS *class = get_progid_class( progid );
|
|
|
|
if (!class || !class->ProgID) return FALSE;
|
|
|
|
return (class->action == INSTALLSTATE_ABSENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL has_extensions( const MSIPACKAGE *package, const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
const MSIEXTENSION *extension;
|
|
|
|
LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
|
|
|
if (extension->ProgID == progid && !list_empty( &extension->verbs )) return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL has_all_extensions_removed( const MSIPACKAGE *package, const MSIPROGID *progid )
|
|
|
|
{
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
const MSIEXTENSION *extension;
|
|
|
|
LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
|
|
|
if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
|
|
|
|
extension->action == INSTALLSTATE_ABSENT) ret = TRUE;
|
|
|
|
else ret = FALSE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
|
|
|
|
{
|
|
|
|
MSIPROGID *progid;
|
|
|
|
MSIRECORD *uirow;
|
|
|
|
LONG res;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
|
|
|
|
{
|
2014-04-23 14:48:52 +00:00
|
|
|
if (!has_class_removed( progid ) ||
|
|
|
|
(has_extensions( package, progid ) && !has_all_extensions_removed( package, progid )))
|
2010-05-29 08:55:43 +00:00
|
|
|
{
|
|
|
|
TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
|
|
|
|
|
2015-11-21 16:44:38 +00:00
|
|
|
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
|
2010-05-29 08:55:43 +00:00
|
|
|
if (res != ERROR_SUCCESS)
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
TRACE("Failed to delete progid key %d\n", res);
|
2010-05-29 08:55:43 +00:00
|
|
|
|
|
|
|
uirow = MSI_CreateRecord( 1 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, progid->ProgID );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2010-05-29 08:55:43 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
|
|
|
|
MSICOMPONENT* component, const MSIEXTENSION* extension,
|
2006-02-17 00:04:10 +00:00
|
|
|
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;
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
keyname = msi_build_directory_name(4, progid, szShell, verb->Verb, szCommand);
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
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 = msi_alloc(size * sizeof (WCHAR));
|
|
|
|
if (verb->Argument)
|
|
|
|
sprintfW(command, fmt, component->FullKeypath, verb->Argument);
|
|
|
|
else
|
|
|
|
sprintfW(command, fmt2, component->FullKeypath);
|
|
|
|
|
|
|
|
msi_reg_set_val_str( key, NULL, command );
|
|
|
|
msi_free(command);
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
advertise = msi_create_component_advertise_string(package, component,
|
|
|
|
extension->Feature->Feature);
|
2006-02-17 00:04:10 +00:00
|
|
|
size = strlenW(advertise);
|
|
|
|
|
|
|
|
if (verb->Argument)
|
|
|
|
size += strlenW(verb->Argument);
|
|
|
|
size += 4;
|
|
|
|
|
2006-08-01 23:12:11 +00:00
|
|
|
command = msi_alloc_zero(size * sizeof (WCHAR));
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
strcpyW(command,advertise);
|
|
|
|
if (verb->Argument)
|
|
|
|
{
|
|
|
|
strcatW(command,szSpace);
|
|
|
|
strcatW(command,verb->Argument);
|
|
|
|
}
|
|
|
|
|
|
|
|
msi_reg_set_val_multi_str( key, szCommand, command );
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
RegCloseKey(key);
|
|
|
|
msi_free(keyname);
|
|
|
|
msi_free(advertise);
|
|
|
|
msi_free(command);
|
|
|
|
|
|
|
|
if (verb->Command)
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
keyname = msi_build_directory_name( 3, progid, szShell, verb->Verb );
|
2006-02-17 00:04:10 +00:00
|
|
|
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Command );
|
|
|
|
msi_free(keyname);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (verb->Sequence != MSI_NULL_INTEGER)
|
|
|
|
{
|
|
|
|
if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
|
|
|
|
{
|
|
|
|
*Sequence = verb->Sequence;
|
2012-01-21 17:19:12 +00:00
|
|
|
keyname = msi_build_directory_name( 2, progid, szShell );
|
2006-02-17 00:04:10 +00:00
|
|
|
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Verb );
|
|
|
|
msi_free(keyname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR szContentType[] = {'C','o','n','t','e','n','t',' ','T','y','p','e',0};
|
2010-05-29 08:55:43 +00:00
|
|
|
HKEY hkey = NULL;
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIEXTENSION *ext;
|
|
|
|
MSIRECORD *uirow;
|
|
|
|
BOOL install_on_demand = TRUE;
|
2010-05-29 08:55:43 +00:00
|
|
|
LONG res;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
|
|
|
LPWSTR extension;
|
|
|
|
MSIFEATURE *feature;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
if (!ext->Component)
|
|
|
|
continue;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (!ext->Component->Enabled)
|
|
|
|
{
|
|
|
|
TRACE("component is disabled\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
feature = ext->Feature;
|
2010-03-01 12:01:30 +00:00
|
|
|
if (!feature)
|
|
|
|
continue;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
/*
|
2006-02-17 00:04:10 +00:00
|
|
|
* yes. MSDN says that these are based on _Feature_ not on
|
|
|
|
* Component. So verify the feature is to be installed
|
|
|
|
*/
|
2012-01-21 17:19:12 +00:00
|
|
|
feature->Action = msi_get_feature_action( package, feature );
|
|
|
|
if (feature->Action != INSTALLSTATE_LOCAL &&
|
|
|
|
!(install_on_demand && feature->Action == INSTALLSTATE_ADVERTISED))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
TRACE("feature %s not scheduled for installation, skipping registration of extension %s\n",
|
|
|
|
debugstr_w(feature->Feature), debugstr_w(ext->Extension));
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext);
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
ext->action = INSTALLSTATE_LOCAL;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
|
|
|
|
if (extension)
|
|
|
|
{
|
|
|
|
extension[0] = '.';
|
|
|
|
strcpyW( extension + 1, ext->Extension );
|
|
|
|
res = RegCreateKeyW( HKEY_CLASSES_ROOT, extension, &hkey );
|
|
|
|
msi_free( extension );
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to create extension key %d\n", res);
|
|
|
|
}
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
if (ext->Mime)
|
|
|
|
msi_reg_set_val_str( hkey, szContentType, ext->Mime->ContentType );
|
|
|
|
|
|
|
|
if (ext->ProgID || ext->ProgIDText)
|
|
|
|
{
|
2008-01-16 10:11:22 +00:00
|
|
|
static const WCHAR szSN[] =
|
2006-02-17 00:04:10 +00:00
|
|
|
{'\\','S','h','e','l','l','N','e','w',0};
|
|
|
|
HKEY hkey2;
|
|
|
|
LPWSTR newkey;
|
|
|
|
LPCWSTR progid;
|
|
|
|
MSIVERB *verb;
|
|
|
|
INT Sequence = MSI_NULL_INTEGER;
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
if (ext->ProgID)
|
|
|
|
progid = ext->ProgID->ProgID;
|
|
|
|
else
|
|
|
|
progid = ext->ProgIDText;
|
|
|
|
|
|
|
|
msi_reg_set_val_str( hkey, NULL, progid );
|
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
newkey = msi_alloc( (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR));
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
strcpyW(newkey,progid);
|
|
|
|
strcatW(newkey,szSN);
|
|
|
|
RegCreateKeyW(hkey,newkey,&hkey2);
|
|
|
|
RegCloseKey(hkey2);
|
|
|
|
|
|
|
|
msi_free(newkey);
|
|
|
|
|
|
|
|
/* do all the verbs */
|
|
|
|
LIST_FOR_EACH_ENTRY( verb, &ext->verbs, MSIVERB, entry )
|
|
|
|
{
|
|
|
|
register_verb( package, progid, ext->Component,
|
|
|
|
ext, verb, &Sequence);
|
|
|
|
}
|
|
|
|
}
|
2008-01-16 10:11:22 +00:00
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
|
|
|
uirow = MSI_CreateRecord(1);
|
|
|
|
MSI_RecordSetStringW( uirow, 1, ext->Extension );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2006-02-17 00:04:10 +00:00
|
|
|
msiobj_release(&uirow->hdr);
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
|
|
|
|
{
|
|
|
|
MSIEXTENSION *ext;
|
|
|
|
MSIRECORD *uirow;
|
|
|
|
LONG res;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
|
|
|
|
{
|
|
|
|
LPWSTR extension;
|
|
|
|
MSIFEATURE *feature;
|
|
|
|
|
|
|
|
if (!ext->Component)
|
|
|
|
continue;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if (!ext->Component->Enabled)
|
|
|
|
{
|
|
|
|
TRACE("component is disabled\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
feature = ext->Feature;
|
|
|
|
if (!feature)
|
|
|
|
continue;
|
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
feature->Action = msi_get_feature_action( package, feature );
|
|
|
|
if (feature->Action != INSTALLSTATE_ABSENT)
|
2010-05-29 08:55:43 +00:00
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
TRACE("feature %s not scheduled for removal, skipping unregistration of extension %s\n",
|
|
|
|
debugstr_w(feature->Feature), debugstr_w(ext->Extension));
|
2010-05-29 08:55:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension));
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
ext->action = INSTALLSTATE_ABSENT;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
|
|
|
extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) );
|
|
|
|
if (extension)
|
|
|
|
{
|
|
|
|
extension[0] = '.';
|
|
|
|
strcpyW( extension + 1, ext->Extension );
|
2015-11-21 16:44:38 +00:00
|
|
|
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
|
2010-05-29 08:55:43 +00:00
|
|
|
msi_free( extension );
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete extension key %d\n", res);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ext->ProgID || ext->ProgIDText)
|
|
|
|
{
|
|
|
|
static const WCHAR shellW[] = {'\\','s','h','e','l','l',0};
|
|
|
|
LPCWSTR progid;
|
|
|
|
LPWSTR progid_shell;
|
|
|
|
|
|
|
|
if (ext->ProgID)
|
|
|
|
progid = ext->ProgID->ProgID;
|
|
|
|
else
|
|
|
|
progid = ext->ProgIDText;
|
|
|
|
|
|
|
|
progid_shell = msi_alloc( (strlenW( progid ) + strlenW( shellW ) + 1) * sizeof(WCHAR) );
|
|
|
|
if (progid_shell)
|
|
|
|
{
|
|
|
|
strcpyW( progid_shell, progid );
|
|
|
|
strcatW( progid_shell, shellW );
|
2015-11-21 16:44:38 +00:00
|
|
|
res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
|
2010-05-29 08:55:43 +00:00
|
|
|
msi_free( progid_shell );
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete shell key %d\n", res);
|
|
|
|
RegDeleteKeyW( HKEY_CLASSES_ROOT, progid );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uirow = MSI_CreateRecord( 1 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, ext->Extension );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2010-05-29 08:55:43 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-02-17 00:04:10 +00:00
|
|
|
UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
|
|
|
|
{
|
2012-01-21 17:19:12 +00:00
|
|
|
static const WCHAR szExtension[] = {'E','x','t','e','n','s','i','o','n',0};
|
2006-02-17 00:04:10 +00:00
|
|
|
MSIRECORD *uirow;
|
|
|
|
MSIMIME *mt;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
|
|
|
|
{
|
2014-09-23 18:32:48 +00:00
|
|
|
LPWSTR extension = NULL, key;
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2008-01-16 10:11:22 +00:00
|
|
|
/*
|
|
|
|
* check if the MIME is to be installed. Either as requested by an
|
2006-02-17 00:04:10 +00:00
|
|
|
* extension or Class
|
|
|
|
*/
|
2014-04-23 14:48:52 +00:00
|
|
|
if ((!mt->Class || mt->Class->action != INSTALLSTATE_LOCAL) &&
|
2014-09-23 18:32:48 +00:00
|
|
|
(!mt->Extension || mt->Extension->action != INSTALLSTATE_LOCAL))
|
2006-02-17 00:04:10 +00:00
|
|
|
{
|
2010-05-29 08:55:43 +00:00
|
|
|
TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType));
|
2006-02-17 00:04:10 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
TRACE("Registering MIME type %s\n", debugstr_w(mt->ContentType));
|
|
|
|
|
2014-09-23 18:32:48 +00:00
|
|
|
if (mt->Extension) extension = msi_alloc( (strlenW( mt->Extension->Extension ) + 2) * sizeof(WCHAR) );
|
2010-05-29 08:55:43 +00:00
|
|
|
key = msi_alloc( (strlenW( mt->ContentType ) + strlenW( szMIMEDatabase ) + 1) * sizeof(WCHAR) );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
if (extension && key)
|
|
|
|
{
|
|
|
|
extension[0] = '.';
|
|
|
|
strcpyW( extension + 1, mt->Extension->Extension );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
strcpyW( key, szMIMEDatabase );
|
|
|
|
strcatW( key, mt->ContentType );
|
2012-01-21 17:19:12 +00:00
|
|
|
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szExtension, extension );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
if (mt->clsid)
|
|
|
|
msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szCLSID, mt->clsid );
|
|
|
|
}
|
|
|
|
msi_free( extension );
|
|
|
|
msi_free( key );
|
2006-02-17 00:04:10 +00:00
|
|
|
|
2010-05-29 08:55:43 +00:00
|
|
|
uirow = MSI_CreateRecord( 2 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, mt->ContentType );
|
|
|
|
MSI_RecordSetStringW( uirow, 2, mt->suffix );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2010-05-29 08:55:43 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
|
|
|
|
{
|
|
|
|
MSIRECORD *uirow;
|
|
|
|
MSIMIME *mime;
|
2012-01-21 17:19:12 +00:00
|
|
|
UINT r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
2012-01-21 17:19:12 +00:00
|
|
|
r = load_classes_and_such( package );
|
|
|
|
if (r != ERROR_SUCCESS)
|
|
|
|
return r;
|
2010-05-29 08:55:43 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY( mime, &package->mimes, MSIMIME, entry )
|
|
|
|
{
|
|
|
|
LONG res;
|
|
|
|
LPWSTR mime_key;
|
|
|
|
|
2014-04-23 14:48:52 +00:00
|
|
|
if ((!mime->Class || mime->Class->action != INSTALLSTATE_ABSENT) &&
|
2014-09-23 18:32:48 +00:00
|
|
|
(!mime->Extension || mime->Extension->action != INSTALLSTATE_ABSENT))
|
2010-05-29 08:55:43 +00:00
|
|
|
{
|
|
|
|
TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
TRACE("Unregistering MIME type %s\n", debugstr_w(mime->ContentType));
|
|
|
|
|
|
|
|
mime_key = msi_alloc( (strlenW( szMIMEDatabase ) + strlenW( mime->ContentType ) + 1) * sizeof(WCHAR) );
|
|
|
|
if (mime_key)
|
|
|
|
{
|
|
|
|
strcpyW( mime_key, szMIMEDatabase );
|
|
|
|
strcatW( mime_key, mime->ContentType );
|
|
|
|
res = RegDeleteKeyW( HKEY_CLASSES_ROOT, mime_key );
|
|
|
|
if (res != ERROR_SUCCESS)
|
|
|
|
WARN("Failed to delete MIME key %d\n", res);
|
|
|
|
msi_free( mime_key );
|
|
|
|
}
|
|
|
|
|
|
|
|
uirow = MSI_CreateRecord( 2 );
|
|
|
|
MSI_RecordSetStringW( uirow, 1, mime->ContentType );
|
|
|
|
MSI_RecordSetStringW( uirow, 2, mime->suffix );
|
2017-10-08 08:14:40 +00:00
|
|
|
MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
|
2010-05-29 08:55:43 +00:00
|
|
|
msiobj_release( &uirow->hdr );
|
2006-02-17 00:04:10 +00:00
|
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|