Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

554 lines
16 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2000
//
// File: Catalog.cxx
//
// Contents: Used to manage catalog(s) state
//
// History: 27-Nov-1996 KyleP Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <catalog.hxx>
#include <catadmin.hxx>
#include <fsciexps.hxx>
//
// Local prototypes
//
WCHAR * ConvertToString ( GUID & Uuid, WCHAR * String );
WCHAR * ULongToHexString ( WCHAR * String, unsigned long Number );
//
// Global data
//
SPropertyColumn coldefProps[] = { { CCachedProperty::GetPropSet, MSG_COL_PROPSET, LVCFMT_LEFT },
{ CCachedProperty::GetProperty, MSG_COL_PROPERTY, LVCFMT_LEFT },
{ CCachedProperty::GetFName, MSG_COL_FNAME, LVCFMT_LEFT },
{ CCachedProperty::GetDatatype, MSG_COL_DATATYPE, LVCFMT_LEFT },
{ CCachedProperty::GetAllocation, MSG_COL_DATASIZE, LVCFMT_LEFT },
{ CCachedProperty::GetStoreLevel, MSG_COL_STORELEVEL, LVCFMT_LEFT }
};
const unsigned cColDefProps = sizeof coldefProps / sizeof coldefProps[0];
BOOL CCachedProperty::_fFirstTime = TRUE;
WCHAR * awcsType[] = { L"VT_EMPTY", // 0
L"VT_NULL", // 1
L"VT_I2", // 2
L"VT_I4", // 3
L"VT_R4", // 4
L"VT_R8", // 5
L"VT_CY", // 6
L"VT_DATE", // 7
L"VT_BSTR", // 8
0, // 9
L"VT_ERROR", // 10
L"VT_BOOL", // 11
L"VT_VARIANT", // 12
0, // 13
L"VT_DECIMAL", // 14
0, // 15
L"VT_I1", // 16
L"VT_UI1", // 17
L"VT_UI2", // 18
L"VT_UI4", // 19
L"VT_I8", // 20
L"VT_UI8", // 21
L"VT_INT", // 22
L"VT_UINT", // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
L"VT_LPSTR", // 30
L"VT_LPWSTR", // 31
0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
0, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
0, // 47
0, // 48
0, // 49
0, // 50
0, // 51
0, // 52
0, // 53
0, // 54
0, // 55
0, // 56
0, // 57
0, // 58
0, // 59
0, // 60
0, // 61
0, // 62
0, // 63
L"VT_FILETIME", // 64
L"VT_BLOB", // 65
0, // 66
0, // 67
0, // 68
0, // 69
0, // 70
L"VT_CF", // 71
L"VT_CLSID" }; // 72
//
// Index of string in packed list box.
//
ULONG aulTypeIndex[] = { 0, // VT_EMPTY
1, // VT_NULL
2, // VT_I2
3, // VT_I4
4, // VT_R4
5, // VT_R8
6, // VT_CY
7, // VT_DATE
8, // VT_BSTR
0, // 9
9, // VT_ERROR
10, // VT_BOOL
11, // VT_VARIANT
0, // 13
12, // 14
0, // 15
13, // VT_I1
14, // VT_UI1
15, // VT_UI2
16, // VT_UI4
17, // VT_I8
18, // VT_UI8
19, // VT_INT
20, // VT_UINT
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
21, // VT_LPSTR
22, // VT_LPWSTR
0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
0, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
0, // 47
0, // 48
0, // 49
0, // 50
0, // 51
0, // 52
0, // 53
0, // 54
0, // 55
0, // 56
0, // 57
0, // 58
0, // 59
0, // 60
0, // 61
0, // 62
0, // 63
23, // VT_FILETIME
24, // VT_BLOB
0, // 66
0, // 67
0, // 68
0, // 69
0, // 70
25, // VT_CF
26 }; // VT_CLSID
CCachedProperty::CCachedProperty( CCatalog & cat,
GUID & guidPropSet,
PROPSPEC & psProperty,
ULONG vt,
ULONGLONG cbAllocation,
DWORD dwStoreLevel,
VARIANT_BOOL fModifiable,
BOOL fNew )
: _vt( vt ),
_cb( (ULONG)cbAllocation ),
_fZombie( FALSE ),
_fNew( fNew ),
_fFixed( FALSE ),
_fUnapplied( FALSE ),
_cat( cat ),
_dwStoreLevel( dwStoreLevel ),
_fModifiable( fModifiable )
{
WCHAR wcsFileName[MAX_PATH];
Win4Assert( (_dwStoreLevel != INVALID_STORE_LEVEL) ||
(_dwStoreLevel == INVALID_STORE_LEVEL && 0 == cbAllocation) );
_regEntry.GetDefaultColumnFile( wcsFileName, MAX_PATH );
//
// Get the file name from the registry and create a list that
// will not be refreshed even if the underlying file changes.
//
_xPropList.Set(new CLocalGlobalPropertyList(GetGlobalStaticPropertyList(),
FALSE,
wcsFileName));
if (_fFirstTime)
{
for ( unsigned i = 0; i < cColDefProps; i++ )
coldefProps[i].srTitle.Init( ghInstance );
_fFirstTime = FALSE;
}
CDbColId dbcol;
dbcol.SetPropSet( guidPropSet );
_fps.guidPropSet = guidPropSet;
_fps.psProperty = psProperty;
//
// String-ize GUID
//
ConvertToString( guidPropSet, _wcsPropSet );
//
// String-ize property
//
if ( PRSPEC_LPWSTR == psProperty.ulKind )
{
unsigned cc = wcslen( psProperty.lpwstr ) + 1;
_xwcsProperty.SetSize( cc );
RtlCopyMemory( _xwcsProperty.Get(), psProperty.lpwstr, cc * sizeof( WCHAR ) );
_fps.psProperty.lpwstr = _xwcsProperty.Get();
dbcol.SetProperty( psProperty.lpwstr );
}
else
{
wcscpy( _xwcsProperty.Get(), L"0x" );
_ultow( psProperty.propid, _xwcsProperty.Get() + 2, 16 );
dbcol.SetProperty( psProperty.propid );
}
if ( vt == VT_EMPTY && 0 == cbAllocation )
{
_wcsDatatype[0] = 0;
_wcsAllocation[0] = 0;
Win4Assert(VT_EMPTY == DBTYPE_EMPTY);
_dbtDefaultType = VT_EMPTY;
_uiDefaultSize = 0;
}
else
SetVT( vt );
//
// Look for friendly name and other details.
//
CPropEntry const * pProp = _xPropList->Find( dbcol );
if ( 0 == pProp )
_xwcsFName[0] = 0;
else
{
unsigned cc = wcslen( pProp->GetDisplayName() ) + 1;
_xwcsFName.SetSize( cc );
RtlCopyMemory( _xwcsFName.Get(), pProp->GetDisplayName(), cc * sizeof(WCHAR) );
_dbtDefaultType = pProp->GetPropType();
_uiDefaultSize = pProp->GetWidth();
ciaDebugOut((DEB_ITRACE, "%ws has type %d (0x%x) and size %d\n",
pProp->GetDisplayName(), _dbtDefaultType, _dbtDefaultType, _uiDefaultSize));
}
// If it is not cached, it can be modified!
if (!IsCached())
_fModifiable = VARIANT_TRUE;
END_CONSTRUCTION( CCachedProperty );
}
CCachedProperty::CCachedProperty( CCachedProperty const & prop )
: _cat( prop._cat ),
_xwcsProperty( prop._xwcsProperty )
{
*this = prop;
END_CONSTRUCTION( CCachedProperty );
}
CCachedProperty & CCachedProperty::operator =( CCachedProperty const & prop )
{
_vt = prop._vt;
_cb = prop._cb;
_fZombie = prop._fZombie;
_fNew = prop._fNew;
_fFixed = prop._fFixed;
_fUnapplied = prop._fUnapplied;
_fps = prop._fps;
_dwStoreLevel = prop._dwStoreLevel;
_fModifiable = prop._fModifiable;
_dbtDefaultType = prop._dbtDefaultType;
_uiDefaultSize = prop._uiDefaultSize;
RtlCopyMemory( _wcsPropSet, prop._wcsPropSet, sizeof( _wcsPropSet ) );
RtlCopyMemory( _wcsDatatype, prop._wcsDatatype, sizeof( _wcsDatatype ) );
RtlCopyMemory( _wcsAllocation, prop._wcsAllocation, sizeof( _wcsAllocation ) );
_xwcsProperty = prop._xwcsProperty;
if ( PRSPEC_LPWSTR == _fps.psProperty.ulKind )
_fps.psProperty.lpwstr = _xwcsProperty.Get();
return *this;
}
CCachedProperty::~CCachedProperty()
{
}
void CCachedProperty::SetVT( ULONG vt )
{
ciaDebugOut(( DEB_ITRACE, "SetVT: _cb is %d before\n", _cb ));
_vt = vt;
//
// Adjust size for fixed types.
//
switch ( _vt )
{
case VT_I1:
case VT_UI1:
_cb = 1;
_fFixed = TRUE;
break;
case VT_I2:
case VT_UI2:
case VT_BOOL:
_cb = 2;
_fFixed = TRUE;
break;
case VT_I4:
case VT_UI4:
case VT_R4:
case VT_ERROR:
_cb = 4;
_fFixed = TRUE;
break;
case VT_I8:
case VT_UI8:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_FILETIME:
_cb = 8;
_fFixed = TRUE;
break;
case VT_CLSID:
_cb = sizeof(GUID);
_fFixed = TRUE;
break;
default:
_fFixed = FALSE;
}
// If storage level is INVALID_STORE_LEVEL, the property is not cached
// so its allocation size should be set to 0.
if (_dwStoreLevel == INVALID_STORE_LEVEL)
_cb = 0;
//
// String-ize datatype
//
if ( vt & VT_VECTOR )
{
wcscpy( _wcsDatatype, L"VT_VECTOR | " );
vt &= ~VT_VECTOR;
}
else
_wcsDatatype[0] = 0;
if ( ( vt >= sizeof(awcsType)/sizeof(awcsType[0]) ) ||
( 0 == awcsType[vt] ) )
{
wcscpy( _wcsDatatype, L"---" );
}
else
wcscat( _wcsDatatype, awcsType[vt] );
//
// String-ize allocation. Assume < 4 Gb!
//
ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty is %ws and pointer is %d before\n", _xwcsProperty.Get(), _xwcsProperty.Get() ));
ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsAllocation is %ws before\n", _wcsAllocation ));
// Max is 60K to fit a record into one page
if ( _cb < 61440 )
_ultow( _cb, _wcsAllocation, 10 );
else
{
_cb = 61440;
_ultow( 61440, _wcsAllocation, 10 );
}
ciaDebugOut(( DEB_ITRACE, "SetVT: _cb is %d after\n", _cb ));
ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty: pointer is %d\n", _xwcsProperty.Get() ));
ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsAllocation is %ws after\n", _wcsAllocation ));
ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty is %ws\n", _xwcsProperty.Get() ));
}
void CCachedProperty::InitHeader( CListViewHeader & Header )
{
if (_fFirstTime)
{
for ( unsigned i = 0; i < cColDefProps; i++ )
coldefProps[i].srTitle.Init( ghInstance );
_fFirstTime = FALSE;
}
//
// Initialize header
//
for ( unsigned i = 0; i < cColDefProps; i++ )
{
Header.Add( i, STRINGRESOURCE(coldefProps[i].srTitle), coldefProps[i].justify, MMCLV_AUTO );
}
}
void CCachedProperty::GetDisplayInfo( RESULTDATAITEM * item )
{
//
// This can happen if you right-click on properties and select refresh
// while the current selection is something other than properties.
// Looks like an MMC bug.
//
if ( item->nCol >= cColDefProps )
{
item->str = L"";
return;
}
item->str = (WCHAR *)(this->*coldefProps[item->nCol].pfGet)();
if ( 0 == item->nCol && IsUnappliedChange() )
{
item->nImage = ICON_MODIFIED_PROPERTY;
item->mask |= RDI_IMAGE;
}
else
item->nImage = ICON_PROPERTY;
} //GetDisplayInfo
static WCHAR HexDigits[] = L"0123456789abcdef";
static WCHAR * ULongToHexString ( WCHAR * String, unsigned long Number )
{
*String++ = HexDigits[(Number >> 28) & 0x0F];
*String++ = HexDigits[(Number >> 24) & 0x0F];
*String++ = HexDigits[(Number >> 20) & 0x0F];
*String++ = HexDigits[(Number >> 16) & 0x0F];
*String++ = HexDigits[(Number >> 12) & 0x0F];
*String++ = HexDigits[(Number >> 8) & 0x0F];
*String++ = HexDigits[(Number >> 4) & 0x0F];
*String++ = HexDigits[Number & 0x0F];
return(String);
}
static WCHAR * UShortToHexString ( WCHAR * String, unsigned short Number )
{
*String++ = HexDigits[(Number >> 12) & 0x0F];
*String++ = HexDigits[(Number >> 8) & 0x0F];
*String++ = HexDigits[(Number >> 4) & 0x0F];
*String++ = HexDigits[Number & 0x0F];
return(String);
}
static WCHAR * UCharToHexString ( WCHAR * String, WCHAR Number )
{
*String++ = HexDigits[(Number >> 4) & 0x0F];
*String++ = HexDigits[Number & 0x0F];
return(String);
}
WCHAR * ConvertToString ( UUID & Uuid, WCHAR * String )
{
String = ULongToHexString(String, Uuid.Data1);
*String++ = L'-';
String = UShortToHexString(String, Uuid.Data2);
*String++ = L'-';
String = UShortToHexString(String, Uuid.Data3);
*String++ = L'-';
String = UCharToHexString(String, Uuid.Data4[0]);
String = UCharToHexString(String, Uuid.Data4[1]);
*String++ = L'-';
String = UCharToHexString(String, Uuid.Data4[2]);
String = UCharToHexString(String, Uuid.Data4[3]);
String = UCharToHexString(String, Uuid.Data4[4]);
String = UCharToHexString(String, Uuid.Data4[5]);
String = UCharToHexString(String, Uuid.Data4[6]);
String = UCharToHexString(String, Uuid.Data4[7]);
*String++ = 0;
return(String);
}