📄 classes.c
字号:
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2005 Aric Stewart for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* actions handled in this module
* RegisterClassInfo
* RegisterProgIdInfo
* RegisterExtensionInfo
* RegisterMIMEInfo
* UnRegisterClassInfo (TODO)
* UnRegisterProgIdInfo (TODO)
* UnRegisterExtensionInfo (TODO)
* UnRegisterMIMEInfo (TODO)
*/
#include <stdarg.h>
#include "stdio.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
#include "wine/debug.h"
#include "msipriv.h"
#include "winuser.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
extern const WCHAR szRegisterClassInfo[];
extern const WCHAR szRegisterProgIdInfo[];
extern const WCHAR szRegisterExtensionInfo[];
extern const WCHAR szRegisterMIMEInfo[];
extern const WCHAR szUnregisterClassInfo[];
extern const WCHAR szUnregisterExtensionInfo[];
extern const WCHAR szUnregisterMIMEInfo[];
extern const WCHAR szUnregisterProgIdInfo[];
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;
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 );
return appid;
}
static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
{
MSIRECORD *row;
MSIAPPID *appid;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','A','p','p','I','d','`',' ','W','H','E','R','E',' ',
'`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0};
if (!name)
return NULL;
/* check for appids already loaded */
LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
{
if (lstrcmpiW( appid->AppID, name )==0)
{
TRACE("found appid %s %p\n", debugstr_w(name), appid);
return appid;
}
}
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, name);
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))
{
INT icon_index = MSI_RecordGetInteger(row,6);
LPCWSTR FileName = MSI_RecordGetString(row,5);
LPWSTR FilePath;
static const WCHAR fmt[] = {'%','s',',','%','i',0};
FilePath = build_icon_path(package,FileName);
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)
progid->IconPath = build_icon_path(package,buffer);
}
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;
/* FIXME: need to determing if we are really the CurVer */
progid->CurVer = parent;
parent->VersionInd = progid;
}
return progid;
}
static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
{
MSIPROGID *progid;
MSIRECORD *row;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ',
'`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0};
if (!name)
return NULL;
/* check for progids already loaded */
LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
{
if (strcmpiW( progid->ProgID,name )==0)
{
TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
return progid;
}
}
row = MSI_QueryGetRecord( package->db, ExecSeqQuery, name );
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);
cls->Component = get_loaded_component(package, buffer);
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))
{
INT icon_index = MSI_RecordGetInteger(row,9);
LPCWSTR FileName = MSI_RecordGetString(row,8);
LPWSTR FilePath;
static const WCHAR fmt[] = {'%','s',',','%','i',0};
FilePath = build_icon_path(package,FileName);
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)
cls->IconPath = build_icon_path(package,buffer);
}
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
{
cls->DefInprocHandler32 = msi_dup_record_field( row, 10);
reduce_to_longfilename(cls->DefInprocHandler32);
}
}
buffer = MSI_RecordGetString(row,11);
deformat_string(package,buffer,&cls->Argument);
buffer = MSI_RecordGetString(row,12);
cls->Feature = get_loaded_feature(package,buffer);
cls->Attributes = MSI_RecordGetInteger(row,13);
return cls;
}
/*
* the Class table has 3 primary keys. Generally it is only
* referenced through the first CLSID key. However when loading
* all of the classes we need to make sure we do not ignore rows
* with other Context and ComponentIndexs
*/
static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
{
MSICLASS *cls;
MSIRECORD *row;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','C','l','a','s','s','`',' ','W','H','E','R','E',' ',
'`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0};
if (!classid)
return NULL;
/* check for classes already loaded */
LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
{
if (lstrcmpiW( cls->clsid, classid )==0)
{
TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
return cls;
}
}
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, classid);
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 )
{
LPCWSTR buffer;
MSIMIME *mt;
/* fill in the data */
mt = msi_alloc_zero( sizeof(MSIMIME) );
if (!mt)
return mt;
mt->ContentType = msi_dup_record_field( row, 1 );
TRACE("loading mime %s\n", debugstr_w(mt->ContentType));
buffer = MSI_RecordGetString( row, 2 );
mt->Extension = load_given_extension( package, buffer );
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 )
{
MSIRECORD *row;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','M','I','M','E','`',' ','W','H','E','R','E',' ',
'`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ',
'\'','%','s','\'',0};
MSIMIME *mt;
if (!mime)
return NULL;
/* check for mime already loaded */
LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
{
if (strcmpiW(mt->ContentType,mime)==0)
{
TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
return mt;
}
}
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, mime);
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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -