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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000
  5. //
  6. // File: Catalog.cxx
  7. //
  8. // Contents: Used to manage catalog(s) state
  9. //
  10. // History: 27-Nov-1996 KyleP Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <catalog.hxx>
  16. #include <catadmin.hxx>
  17. #include <fsciexps.hxx>
  18. //
  19. // Local prototypes
  20. //
  21. WCHAR * ConvertToString ( GUID & Uuid, WCHAR * String );
  22. WCHAR * ULongToHexString ( WCHAR * String, unsigned long Number );
  23. //
  24. // Global data
  25. //
  26. SPropertyColumn coldefProps[] = { { CCachedProperty::GetPropSet, MSG_COL_PROPSET, LVCFMT_LEFT },
  27. { CCachedProperty::GetProperty, MSG_COL_PROPERTY, LVCFMT_LEFT },
  28. { CCachedProperty::GetFName, MSG_COL_FNAME, LVCFMT_LEFT },
  29. { CCachedProperty::GetDatatype, MSG_COL_DATATYPE, LVCFMT_LEFT },
  30. { CCachedProperty::GetAllocation, MSG_COL_DATASIZE, LVCFMT_LEFT },
  31. { CCachedProperty::GetStoreLevel, MSG_COL_STORELEVEL, LVCFMT_LEFT }
  32. };
  33. const unsigned cColDefProps = sizeof coldefProps / sizeof coldefProps[0];
  34. BOOL CCachedProperty::_fFirstTime = TRUE;
  35. WCHAR * awcsType[] = { L"VT_EMPTY", // 0
  36. L"VT_NULL", // 1
  37. L"VT_I2", // 2
  38. L"VT_I4", // 3
  39. L"VT_R4", // 4
  40. L"VT_R8", // 5
  41. L"VT_CY", // 6
  42. L"VT_DATE", // 7
  43. L"VT_BSTR", // 8
  44. 0, // 9
  45. L"VT_ERROR", // 10
  46. L"VT_BOOL", // 11
  47. L"VT_VARIANT", // 12
  48. 0, // 13
  49. L"VT_DECIMAL", // 14
  50. 0, // 15
  51. L"VT_I1", // 16
  52. L"VT_UI1", // 17
  53. L"VT_UI2", // 18
  54. L"VT_UI4", // 19
  55. L"VT_I8", // 20
  56. L"VT_UI8", // 21
  57. L"VT_INT", // 22
  58. L"VT_UINT", // 23
  59. 0, // 24
  60. 0, // 25
  61. 0, // 26
  62. 0, // 27
  63. 0, // 28
  64. 0, // 29
  65. L"VT_LPSTR", // 30
  66. L"VT_LPWSTR", // 31
  67. 0, // 32
  68. 0, // 33
  69. 0, // 34
  70. 0, // 35
  71. 0, // 36
  72. 0, // 37
  73. 0, // 38
  74. 0, // 39
  75. 0, // 40
  76. 0, // 41
  77. 0, // 42
  78. 0, // 43
  79. 0, // 44
  80. 0, // 45
  81. 0, // 46
  82. 0, // 47
  83. 0, // 48
  84. 0, // 49
  85. 0, // 50
  86. 0, // 51
  87. 0, // 52
  88. 0, // 53
  89. 0, // 54
  90. 0, // 55
  91. 0, // 56
  92. 0, // 57
  93. 0, // 58
  94. 0, // 59
  95. 0, // 60
  96. 0, // 61
  97. 0, // 62
  98. 0, // 63
  99. L"VT_FILETIME", // 64
  100. L"VT_BLOB", // 65
  101. 0, // 66
  102. 0, // 67
  103. 0, // 68
  104. 0, // 69
  105. 0, // 70
  106. L"VT_CF", // 71
  107. L"VT_CLSID" }; // 72
  108. //
  109. // Index of string in packed list box.
  110. //
  111. ULONG aulTypeIndex[] = { 0, // VT_EMPTY
  112. 1, // VT_NULL
  113. 2, // VT_I2
  114. 3, // VT_I4
  115. 4, // VT_R4
  116. 5, // VT_R8
  117. 6, // VT_CY
  118. 7, // VT_DATE
  119. 8, // VT_BSTR
  120. 0, // 9
  121. 9, // VT_ERROR
  122. 10, // VT_BOOL
  123. 11, // VT_VARIANT
  124. 0, // 13
  125. 12, // 14
  126. 0, // 15
  127. 13, // VT_I1
  128. 14, // VT_UI1
  129. 15, // VT_UI2
  130. 16, // VT_UI4
  131. 17, // VT_I8
  132. 18, // VT_UI8
  133. 19, // VT_INT
  134. 20, // VT_UINT
  135. 0, // 24
  136. 0, // 25
  137. 0, // 26
  138. 0, // 27
  139. 0, // 28
  140. 0, // 29
  141. 21, // VT_LPSTR
  142. 22, // VT_LPWSTR
  143. 0, // 32
  144. 0, // 33
  145. 0, // 34
  146. 0, // 35
  147. 0, // 36
  148. 0, // 37
  149. 0, // 38
  150. 0, // 39
  151. 0, // 40
  152. 0, // 41
  153. 0, // 42
  154. 0, // 43
  155. 0, // 44
  156. 0, // 45
  157. 0, // 46
  158. 0, // 47
  159. 0, // 48
  160. 0, // 49
  161. 0, // 50
  162. 0, // 51
  163. 0, // 52
  164. 0, // 53
  165. 0, // 54
  166. 0, // 55
  167. 0, // 56
  168. 0, // 57
  169. 0, // 58
  170. 0, // 59
  171. 0, // 60
  172. 0, // 61
  173. 0, // 62
  174. 0, // 63
  175. 23, // VT_FILETIME
  176. 24, // VT_BLOB
  177. 0, // 66
  178. 0, // 67
  179. 0, // 68
  180. 0, // 69
  181. 0, // 70
  182. 25, // VT_CF
  183. 26 }; // VT_CLSID
  184. CCachedProperty::CCachedProperty( CCatalog & cat,
  185. GUID & guidPropSet,
  186. PROPSPEC & psProperty,
  187. ULONG vt,
  188. ULONGLONG cbAllocation,
  189. DWORD dwStoreLevel,
  190. VARIANT_BOOL fModifiable,
  191. BOOL fNew )
  192. : _vt( vt ),
  193. _cb( (ULONG)cbAllocation ),
  194. _fZombie( FALSE ),
  195. _fNew( fNew ),
  196. _fFixed( FALSE ),
  197. _fUnapplied( FALSE ),
  198. _cat( cat ),
  199. _dwStoreLevel( dwStoreLevel ),
  200. _fModifiable( fModifiable )
  201. {
  202. WCHAR wcsFileName[MAX_PATH];
  203. Win4Assert( (_dwStoreLevel != INVALID_STORE_LEVEL) ||
  204. (_dwStoreLevel == INVALID_STORE_LEVEL && 0 == cbAllocation) );
  205. _regEntry.GetDefaultColumnFile( wcsFileName, MAX_PATH );
  206. //
  207. // Get the file name from the registry and create a list that
  208. // will not be refreshed even if the underlying file changes.
  209. //
  210. _xPropList.Set(new CLocalGlobalPropertyList(GetGlobalStaticPropertyList(),
  211. FALSE,
  212. wcsFileName));
  213. if (_fFirstTime)
  214. {
  215. for ( unsigned i = 0; i < cColDefProps; i++ )
  216. coldefProps[i].srTitle.Init( ghInstance );
  217. _fFirstTime = FALSE;
  218. }
  219. CDbColId dbcol;
  220. dbcol.SetPropSet( guidPropSet );
  221. _fps.guidPropSet = guidPropSet;
  222. _fps.psProperty = psProperty;
  223. //
  224. // String-ize GUID
  225. //
  226. ConvertToString( guidPropSet, _wcsPropSet );
  227. //
  228. // String-ize property
  229. //
  230. if ( PRSPEC_LPWSTR == psProperty.ulKind )
  231. {
  232. unsigned cc = wcslen( psProperty.lpwstr ) + 1;
  233. _xwcsProperty.SetSize( cc );
  234. RtlCopyMemory( _xwcsProperty.Get(), psProperty.lpwstr, cc * sizeof( WCHAR ) );
  235. _fps.psProperty.lpwstr = _xwcsProperty.Get();
  236. dbcol.SetProperty( psProperty.lpwstr );
  237. }
  238. else
  239. {
  240. wcscpy( _xwcsProperty.Get(), L"0x" );
  241. _ultow( psProperty.propid, _xwcsProperty.Get() + 2, 16 );
  242. dbcol.SetProperty( psProperty.propid );
  243. }
  244. if ( vt == VT_EMPTY && 0 == cbAllocation )
  245. {
  246. _wcsDatatype[0] = 0;
  247. _wcsAllocation[0] = 0;
  248. Win4Assert(VT_EMPTY == DBTYPE_EMPTY);
  249. _dbtDefaultType = VT_EMPTY;
  250. _uiDefaultSize = 0;
  251. }
  252. else
  253. SetVT( vt );
  254. //
  255. // Look for friendly name and other details.
  256. //
  257. CPropEntry const * pProp = _xPropList->Find( dbcol );
  258. if ( 0 == pProp )
  259. _xwcsFName[0] = 0;
  260. else
  261. {
  262. unsigned cc = wcslen( pProp->GetDisplayName() ) + 1;
  263. _xwcsFName.SetSize( cc );
  264. RtlCopyMemory( _xwcsFName.Get(), pProp->GetDisplayName(), cc * sizeof(WCHAR) );
  265. _dbtDefaultType = pProp->GetPropType();
  266. _uiDefaultSize = pProp->GetWidth();
  267. ciaDebugOut((DEB_ITRACE, "%ws has type %d (0x%x) and size %d\n",
  268. pProp->GetDisplayName(), _dbtDefaultType, _dbtDefaultType, _uiDefaultSize));
  269. }
  270. // If it is not cached, it can be modified!
  271. if (!IsCached())
  272. _fModifiable = VARIANT_TRUE;
  273. END_CONSTRUCTION( CCachedProperty );
  274. }
  275. CCachedProperty::CCachedProperty( CCachedProperty const & prop )
  276. : _cat( prop._cat ),
  277. _xwcsProperty( prop._xwcsProperty )
  278. {
  279. *this = prop;
  280. END_CONSTRUCTION( CCachedProperty );
  281. }
  282. CCachedProperty & CCachedProperty::operator =( CCachedProperty const & prop )
  283. {
  284. _vt = prop._vt;
  285. _cb = prop._cb;
  286. _fZombie = prop._fZombie;
  287. _fNew = prop._fNew;
  288. _fFixed = prop._fFixed;
  289. _fUnapplied = prop._fUnapplied;
  290. _fps = prop._fps;
  291. _dwStoreLevel = prop._dwStoreLevel;
  292. _fModifiable = prop._fModifiable;
  293. _dbtDefaultType = prop._dbtDefaultType;
  294. _uiDefaultSize = prop._uiDefaultSize;
  295. RtlCopyMemory( _wcsPropSet, prop._wcsPropSet, sizeof( _wcsPropSet ) );
  296. RtlCopyMemory( _wcsDatatype, prop._wcsDatatype, sizeof( _wcsDatatype ) );
  297. RtlCopyMemory( _wcsAllocation, prop._wcsAllocation, sizeof( _wcsAllocation ) );
  298. _xwcsProperty = prop._xwcsProperty;
  299. if ( PRSPEC_LPWSTR == _fps.psProperty.ulKind )
  300. _fps.psProperty.lpwstr = _xwcsProperty.Get();
  301. return *this;
  302. }
  303. CCachedProperty::~CCachedProperty()
  304. {
  305. }
  306. void CCachedProperty::SetVT( ULONG vt )
  307. {
  308. ciaDebugOut(( DEB_ITRACE, "SetVT: _cb is %d before\n", _cb ));
  309. _vt = vt;
  310. //
  311. // Adjust size for fixed types.
  312. //
  313. switch ( _vt )
  314. {
  315. case VT_I1:
  316. case VT_UI1:
  317. _cb = 1;
  318. _fFixed = TRUE;
  319. break;
  320. case VT_I2:
  321. case VT_UI2:
  322. case VT_BOOL:
  323. _cb = 2;
  324. _fFixed = TRUE;
  325. break;
  326. case VT_I4:
  327. case VT_UI4:
  328. case VT_R4:
  329. case VT_ERROR:
  330. _cb = 4;
  331. _fFixed = TRUE;
  332. break;
  333. case VT_I8:
  334. case VT_UI8:
  335. case VT_R8:
  336. case VT_CY:
  337. case VT_DATE:
  338. case VT_FILETIME:
  339. _cb = 8;
  340. _fFixed = TRUE;
  341. break;
  342. case VT_CLSID:
  343. _cb = sizeof(GUID);
  344. _fFixed = TRUE;
  345. break;
  346. default:
  347. _fFixed = FALSE;
  348. }
  349. // If storage level is INVALID_STORE_LEVEL, the property is not cached
  350. // so its allocation size should be set to 0.
  351. if (_dwStoreLevel == INVALID_STORE_LEVEL)
  352. _cb = 0;
  353. //
  354. // String-ize datatype
  355. //
  356. if ( vt & VT_VECTOR )
  357. {
  358. wcscpy( _wcsDatatype, L"VT_VECTOR | " );
  359. vt &= ~VT_VECTOR;
  360. }
  361. else
  362. _wcsDatatype[0] = 0;
  363. if ( ( vt >= sizeof(awcsType)/sizeof(awcsType[0]) ) ||
  364. ( 0 == awcsType[vt] ) )
  365. {
  366. wcscpy( _wcsDatatype, L"---" );
  367. }
  368. else
  369. wcscat( _wcsDatatype, awcsType[vt] );
  370. //
  371. // String-ize allocation. Assume < 4 Gb!
  372. //
  373. ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty is %ws and pointer is %d before\n", _xwcsProperty.Get(), _xwcsProperty.Get() ));
  374. ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsAllocation is %ws before\n", _wcsAllocation ));
  375. // Max is 60K to fit a record into one page
  376. if ( _cb < 61440 )
  377. _ultow( _cb, _wcsAllocation, 10 );
  378. else
  379. {
  380. _cb = 61440;
  381. _ultow( 61440, _wcsAllocation, 10 );
  382. }
  383. ciaDebugOut(( DEB_ITRACE, "SetVT: _cb is %d after\n", _cb ));
  384. ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty: pointer is %d\n", _xwcsProperty.Get() ));
  385. ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsAllocation is %ws after\n", _wcsAllocation ));
  386. ciaDebugOut(( DEB_ITRACE, "SetVT: _wcsProperty is %ws\n", _xwcsProperty.Get() ));
  387. }
  388. void CCachedProperty::InitHeader( CListViewHeader & Header )
  389. {
  390. if (_fFirstTime)
  391. {
  392. for ( unsigned i = 0; i < cColDefProps; i++ )
  393. coldefProps[i].srTitle.Init( ghInstance );
  394. _fFirstTime = FALSE;
  395. }
  396. //
  397. // Initialize header
  398. //
  399. for ( unsigned i = 0; i < cColDefProps; i++ )
  400. {
  401. Header.Add( i, STRINGRESOURCE(coldefProps[i].srTitle), coldefProps[i].justify, MMCLV_AUTO );
  402. }
  403. }
  404. void CCachedProperty::GetDisplayInfo( RESULTDATAITEM * item )
  405. {
  406. //
  407. // This can happen if you right-click on properties and select refresh
  408. // while the current selection is something other than properties.
  409. // Looks like an MMC bug.
  410. //
  411. if ( item->nCol >= cColDefProps )
  412. {
  413. item->str = L"";
  414. return;
  415. }
  416. item->str = (WCHAR *)(this->*coldefProps[item->nCol].pfGet)();
  417. if ( 0 == item->nCol && IsUnappliedChange() )
  418. {
  419. item->nImage = ICON_MODIFIED_PROPERTY;
  420. item->mask |= RDI_IMAGE;
  421. }
  422. else
  423. item->nImage = ICON_PROPERTY;
  424. } //GetDisplayInfo
  425. static WCHAR HexDigits[] = L"0123456789abcdef";
  426. static WCHAR * ULongToHexString ( WCHAR * String, unsigned long Number )
  427. {
  428. *String++ = HexDigits[(Number >> 28) & 0x0F];
  429. *String++ = HexDigits[(Number >> 24) & 0x0F];
  430. *String++ = HexDigits[(Number >> 20) & 0x0F];
  431. *String++ = HexDigits[(Number >> 16) & 0x0F];
  432. *String++ = HexDigits[(Number >> 12) & 0x0F];
  433. *String++ = HexDigits[(Number >> 8) & 0x0F];
  434. *String++ = HexDigits[(Number >> 4) & 0x0F];
  435. *String++ = HexDigits[Number & 0x0F];
  436. return(String);
  437. }
  438. static WCHAR * UShortToHexString ( WCHAR * String, unsigned short Number )
  439. {
  440. *String++ = HexDigits[(Number >> 12) & 0x0F];
  441. *String++ = HexDigits[(Number >> 8) & 0x0F];
  442. *String++ = HexDigits[(Number >> 4) & 0x0F];
  443. *String++ = HexDigits[Number & 0x0F];
  444. return(String);
  445. }
  446. static WCHAR * UCharToHexString ( WCHAR * String, WCHAR Number )
  447. {
  448. *String++ = HexDigits[(Number >> 4) & 0x0F];
  449. *String++ = HexDigits[Number & 0x0F];
  450. return(String);
  451. }
  452. WCHAR * ConvertToString ( UUID & Uuid, WCHAR * String )
  453. {
  454. String = ULongToHexString(String, Uuid.Data1);
  455. *String++ = L'-';
  456. String = UShortToHexString(String, Uuid.Data2);
  457. *String++ = L'-';
  458. String = UShortToHexString(String, Uuid.Data3);
  459. *String++ = L'-';
  460. String = UCharToHexString(String, Uuid.Data4[0]);
  461. String = UCharToHexString(String, Uuid.Data4[1]);
  462. *String++ = L'-';
  463. String = UCharToHexString(String, Uuid.Data4[2]);
  464. String = UCharToHexString(String, Uuid.Data4[3]);
  465. String = UCharToHexString(String, Uuid.Data4[4]);
  466. String = UCharToHexString(String, Uuid.Data4[5]);
  467. String = UCharToHexString(String, Uuid.Data4[6]);
  468. String = UCharToHexString(String, Uuid.Data4[7]);
  469. *String++ = 0;
  470. return(String);
  471. }