305 lines
7.1 KiB
C++
305 lines
7.1 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 2001.
|
|
//
|
|
// File: msiclass.h
|
|
//
|
|
// Contents: msi class collection abstraction
|
|
//
|
|
// Classes:
|
|
//
|
|
//
|
|
// History: 4-14-2000 adamed Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#if !defined(__MSICLASS_H__)
|
|
#define __MSICLASS_H__
|
|
|
|
//
|
|
// MSI Tables containing classes
|
|
//
|
|
#define TABLE_FILE_EXTENSIONS L"Extension"
|
|
#define TABLE_CLSIDS L"Class"
|
|
#define TABLE_PROGIDS L"ProgId"
|
|
|
|
|
|
//
|
|
// Package metadata queries
|
|
//
|
|
|
|
//
|
|
// Property table queries -- used to find out global information about the package
|
|
//
|
|
|
|
//
|
|
// This query is used to determine the package's global install level
|
|
//
|
|
#define QUERY_INSTALLLEVEL L"SELECT DISTINCT `Value` FROM `Property` WHERE `Property`=\'INSTALLLEVEL\'"
|
|
|
|
// This query is used to determine the package's friendly name
|
|
//
|
|
#define QUERY_FRIENDLYNAME L"SELECT DISTINCT `Value` FROM `Property` WHERE `Property`=\'ProductName\'"
|
|
|
|
//
|
|
// Feature table queries -- these are used to find out which features will be
|
|
// advertised so that we can later determine if the classes associated with the
|
|
// features should be advertised
|
|
//
|
|
|
|
//
|
|
// This query is less a query and more a modification operation. It adds an additional
|
|
// temporary "_IsAdvertised" column to the table. We use this to perform joins in
|
|
// subsequent queries.
|
|
//
|
|
#define QUERY_ADVERTISED_FEATURES_CREATE L"ALTER TABLE `Feature` ADD `_IsAdvertised` INT TEMPORARY HOLD"
|
|
|
|
//
|
|
// Again, this query really serves as a modification operation. This one initializes the
|
|
// temporary "_IsAdvertised" column to 0, which in our parlance is the same as initializing
|
|
// the column to "not advertised."
|
|
//
|
|
#define QUERY_ADVERTISED_FEATURES_INIT L"UPDATE `Feature` SET `_IsAdvertised`=0"
|
|
|
|
//
|
|
// This is a conventional query -- this returns all the features in the package
|
|
//
|
|
#define QUERY_ADVERTISED_FEATURES_RESULT L"SELECT `Feature`, `Level`, `Attributes` FROM `Feature`"
|
|
|
|
//
|
|
// Another modification query -- this eliminates the temporary changes (the additional
|
|
// column) we made to the table in the create query.
|
|
//
|
|
#define QUERY_ADVERTISED_FEATURES_DESTROY L"ALTER TABLE `Feature` FREE"
|
|
|
|
//
|
|
// The last modification query -- this allows us to set a particular feature's "_IsAdvertised"
|
|
// column to 1, which will indicate that the feature should be advertised.
|
|
//
|
|
#define QUERY_FEATURES_SET L"UPDATE `Feature` SET `_IsAdvertised`=1 WHERE `Feature`=?"
|
|
|
|
//
|
|
// Classes queries -- retrieves file extensions, clsid's, and progid's of the package
|
|
//
|
|
|
|
|
|
//
|
|
// The rest of these queries are straightforward "read-only" queries. They are all joins
|
|
// to the feature table, requiring that the feature table's "_IsAdvertised" property
|
|
// is set to the advertised state (1). Thus, these queries will only give us classes that
|
|
// should be advertised
|
|
//
|
|
|
|
//
|
|
// File extensions query
|
|
//
|
|
#define QUERY_EXTENSIONS L"SELECT DISTINCT `Extension` FROM `Extension`, `Feature` WHERE `Extension` IS NOT NULL " \
|
|
L"AND `Extension`.`Feature_`=`Feature`.`Feature` AND `Feature`.`_IsAdvertised`=1"
|
|
|
|
//
|
|
// Clsid query
|
|
//
|
|
#define QUERY_CLSIDS L"SELECT DISTINCT `CLSID`, `Context`, `Component`.`Attributes` FROM `Class`, `Feature`, " \
|
|
L"`Component` WHERE `CLSID` IS NOT NULL AND `Class`.`Feature_`=`Feature`.`Feature` " \
|
|
L"AND `Feature`.`_IsAdvertised`=1 AND `Component`.`Component`=`Class`.`Component_`"
|
|
|
|
//
|
|
// ProgId query
|
|
//
|
|
#define QUERY_VERSION_INDEPENDENT_PROGIDS L"SELECT DISTINCT `ProgId`,`CLSID` FROM `ProgId`, `Class`, `Feature` WHERE `ProgId` IS NOT NULL " \
|
|
L"AND `ProgId`.`Class_`=`Class`.`CLSID` AND `Class`.`Feature_`=`Feature`.`Feature` " \
|
|
L"AND `Feature`.`_IsAdvertised`=1"
|
|
|
|
//
|
|
// COM clsctx values as they are stored in the package's class (clsid) table
|
|
//
|
|
#define COM_INPROC_CONTEXT L"InprocServer32"
|
|
#define COM_INPROCHANDLER_CONTEXT L"InprocHandler32"
|
|
#define COM_LOCALSERVER_CONTEXT L"LocalServer32"
|
|
#define COM_REMOTESERVER_CONTEXT L"RemoteServer"
|
|
|
|
//
|
|
// MSI attribute flags
|
|
//
|
|
#define MSI_64BIT_CLASS msidbComponentAttributes64bit
|
|
#define MSI_DISABLEADVERTISE msidbFeatureAttributesDisallowAdvertise
|
|
|
|
#define CLASS_ALLOC_SIZE 256
|
|
|
|
//
|
|
// Indices of colums for each read-only query
|
|
//
|
|
|
|
enum
|
|
{
|
|
PROPERTY_COLUMN_VALUE = 1
|
|
};
|
|
|
|
enum
|
|
{
|
|
FEATURE_COLUMN_FEATURE = 1,
|
|
FEATURE_COLUMN_LEVEL,
|
|
FEATURE_COLUMN_ATTRIBUTES
|
|
};
|
|
|
|
enum
|
|
{
|
|
EXTENSION_COLUMN_EXTENSION = 1
|
|
};
|
|
|
|
enum
|
|
{
|
|
CLSID_COLUMN_CLSID = 1,
|
|
CLSID_COLUMN_CONTEXT,
|
|
CLSID_COLUMN_ATTRIBUTES
|
|
};
|
|
|
|
|
|
enum
|
|
{
|
|
PROGID_COLUMN_PROGID = 1,
|
|
PROGID_COLUMN_CLSID
|
|
};
|
|
|
|
enum
|
|
{
|
|
TYPE_EXTENSION,
|
|
TYPE_CLSID,
|
|
TYPE_PROGID,
|
|
TYPE_COUNT
|
|
};
|
|
|
|
|
|
//
|
|
// Structure describing where to write an atom
|
|
// of class information. It is also used as
|
|
// an intermediate scratch pad by CClassCollection
|
|
// in between private method calls to keep track
|
|
// of when and where to allocate new memory
|
|
// for retrieved classes.
|
|
//
|
|
struct DataDestination
|
|
{
|
|
DataDestination(
|
|
DWORD dwType,
|
|
void** prgpvDestination,
|
|
UINT* pcCurrent,
|
|
UINT* pcMax);
|
|
|
|
DWORD _cbElementSize;
|
|
UINT* _pcCurrent;
|
|
UINT* _pcMax;
|
|
|
|
void** _ppvData;
|
|
};
|
|
|
|
|
|
//
|
|
// Class that uses queries to create a collection of
|
|
// a package's class data
|
|
//
|
|
class CClassCollection
|
|
{
|
|
public:
|
|
|
|
CClassCollection( PACKAGEDETAIL* pPackageDetail );
|
|
|
|
HRESULT
|
|
GetClasses( BOOL bFileExtensionsOnly );
|
|
|
|
private:
|
|
|
|
LONG
|
|
GetClsids();
|
|
|
|
LONG
|
|
GetProgIds();
|
|
|
|
LONG
|
|
GetExtensions();
|
|
|
|
LONG
|
|
GetElements(
|
|
DWORD dwType,
|
|
DataDestination* pDestination);
|
|
|
|
LONG
|
|
FlagAdvertisableFeatures();
|
|
|
|
LONG
|
|
RemoveAdvertisableFeatureFlags();
|
|
|
|
LONG
|
|
GetInstallLevel();
|
|
|
|
LONG
|
|
GetFriendlyName();
|
|
|
|
LONG
|
|
GetFeatureAdvertiseState(
|
|
CMsiRecord* pFeatureRecord,
|
|
BOOL* pbAdvertised );
|
|
|
|
|
|
LONG
|
|
AddElement(
|
|
void* pvDataSource,
|
|
DataDestination* pDataDestination);
|
|
|
|
LONG
|
|
ProcessElement(
|
|
DWORD dwType,
|
|
CMsiRecord* pRecord,
|
|
DataDestination* pDataDestination);
|
|
|
|
LONG
|
|
ProcessExtension(
|
|
CMsiRecord* pRecord,
|
|
WCHAR** ppwszExtension);
|
|
|
|
LONG
|
|
ProcessClsid(
|
|
CMsiRecord* pRecord,
|
|
CLASSDETAIL* pClsid,
|
|
BOOL* pbIgnoreClsid);
|
|
|
|
LONG
|
|
ProcessProgId(
|
|
CMsiRecord* pRecord,
|
|
DataDestination* pDataDestination,
|
|
WCHAR** ppwszProgId);
|
|
|
|
LONG
|
|
FindClass(
|
|
WCHAR* wszClsid,
|
|
CLASSDETAIL** ppClass );
|
|
|
|
void
|
|
FreeClassDetail( CLASSDETAIL* pClass );
|
|
|
|
CMsiDatabase _Database;
|
|
|
|
PACKAGEDETAIL* _pPackageDetail;
|
|
|
|
DWORD _cMaxClsids;
|
|
DWORD _cMaxExtensions;
|
|
|
|
UINT _InstallLevel;
|
|
|
|
static WCHAR* _wszQueries[ TYPE_COUNT ];
|
|
};
|
|
|
|
#endif // __MSICLASS_H__
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|