//+------------------------------------------------------------------------- // // 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 #pragma hdrstop #include #include #include // // 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); }