propvar.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 65k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //-------------------------------------------------------------------------//
  2. //
  3. //  PropVar.cpp
  4. //
  5. //-------------------------------------------------------------------------//
  6. #include "pch.h"
  7. #include <stdio.h>
  8. #include "propVar.h"
  9. //-------------------------------------------------------------------------//
  10. static LPCWSTR clipformats[] = 
  11. {
  12.     L"CF_TEXT",           // 1
  13.     L"CF_BITMAP",         // 2
  14.     L"CF_METAFILEPICT",   // 3
  15.     L"CF_SYLK",           // 4
  16.     L"CF_DIF",            // 5
  17.     L"CF_TIFF",           // 6
  18.     L"CF_OEMTEXT",        // 7
  19.     L"CF_DIB",            // 8
  20.     L"CF_PALETTE",        // 9
  21.     L"CF_PENDATA",        // 10
  22.     L"CF_RIFF",           // 11
  23.     L"CF_WAVE",           // 12
  24.     L"CF_UNICODETEXT",    // 13
  25.     L"CF_ENHMETAFILE",    // 14
  26.     L"CF_HDROP",          // 15
  27.     L"CF_LOCALE",         // 16
  28. } ;
  29. #define NUM_CLIPFORMATS sizeof(clipformats)/sizeof(LPCWSTR)
  30. //-------------------------------------------------------------------------//
  31. //  Global PROPVARARIANT utility functions
  32. //-------------------------------------------------------------------------//
  33. //-------------------------------------------------------------------------//
  34. //  Determins the size of the data contained by a PROPVARIANT instance.
  35. //  The returned value does not included the size of the PROPVARIANT structure
  36. //  itself.
  37. HRESULT PropVariantSize( 
  38.     IN const PROPVARIANT& var, 
  39.     OUT ULONG& cbDataSize, 
  40.     OUT OPTIONAL PROPVARIANT_ALLOCTYPE* pdwAllocType )
  41. {
  42.     HRESULT hr = S_OK ;
  43.     ULONG   i ;
  44.     
  45.     cbDataSize  = 0 ;
  46.     
  47.     PROPVARIANT_ALLOCTYPE dwAllocType ;
  48.     if( !pdwAllocType ) pdwAllocType = &dwAllocType ;
  49.     *pdwAllocType = PVAT_NOALLOC ;
  50.     #define PROPVARIANT_VECTOR_SIZE( member ) 
  51.             (sizeof(var.member) + (var.member.cElems * sizeof(*var.member.pElems)))
  52.     
  53.     switch( var.vt )
  54.     {
  55.         case VT_EMPTY:
  56.         case VT_NULL:
  57.         case VT_ILLEGAL:
  58.             break ;
  59.                         
  60.         case VT_UI1:
  61.             cbDataSize = sizeof(var.bVal) ;
  62.             break ;
  63.         case VT_I2:
  64.             cbDataSize = sizeof(var.iVal) ;
  65.             break ;
  66.         case VT_UI2:
  67.             cbDataSize = sizeof(var.uiVal) ;
  68.             break ;
  69.             
  70.         case VT_BOOL:
  71.             cbDataSize = sizeof(var.boolVal) ;
  72.             break ;
  73.         case VT_I4:
  74.             cbDataSize = sizeof(var.lVal) ;
  75.             break ;
  76.  
  77.         case VT_UI4:
  78.             cbDataSize = sizeof(var.ulVal) ;
  79.             break ;
  80.         case VT_R4:
  81.             cbDataSize = sizeof(var.fltVal) ;
  82.             break ;
  83.         case VT_ERROR:
  84.             cbDataSize = sizeof(var.scode) ;
  85.             break ;
  86.         case VT_I8:
  87.             cbDataSize = sizeof(var.hVal) ;
  88.             break ;
  89.         case VT_UI8:
  90.             cbDataSize = sizeof(var.uhVal) ;
  91.         case VT_R8:
  92.             cbDataSize = sizeof(var.dblVal) ;
  93.             break ;
  94.         case VT_CY:
  95.             cbDataSize = sizeof(var.cyVal) ;
  96.             break ;
  97.         case VT_DATE:
  98.             cbDataSize = sizeof(var.date) ;
  99.             break ;
  100.         case VT_FILETIME:
  101.             cbDataSize = sizeof(var.filetime) ;
  102.             break ;
  103.         
  104.         case VT_CLSID:
  105.             cbDataSize = var.puuid ? sizeof(*var.puuid) : 0 ;
  106.             *pdwAllocType = PVAT_SYSALLOC ;
  107.             break ;
  108.         case VT_BLOB:
  109.             cbDataSize = sizeof(BLOB) + var.blob.cbSize ;
  110.             *pdwAllocType = PVAT_COMPLEX ;
  111.             break ;
  112.         case VT_CF :
  113.             cbDataSize = var.pclipdata ? sizeof(CLIPDATA) + CBPCLIPDATA( *var.pclipdata ) : 0 ;
  114.             *pdwAllocType = PVAT_COMPLEX ;
  115.             break ;
  116.         case VT_BSTR:
  117.             cbDataSize  = var.bstrVal ? (lstrlenW( var.bstrVal ) + 1) * sizeof(WCHAR) : 0 ;
  118.             *pdwAllocType = PVAT_STRINGALLOC ;
  119.             break ;
  120.         case VT_LPSTR:
  121.             cbDataSize  = var.pszVal ? (lstrlenA( var.pszVal ) + 1) * sizeof(CHAR) : 0 ;
  122.             *pdwAllocType = PVAT_SYSALLOC ;
  123.             break ;
  124.             
  125.         case VT_LPWSTR:
  126.             cbDataSize  = var.pwszVal ? (lstrlenW( var.pwszVal ) + 1) * sizeof(WCHAR) : 0 ;
  127.             *pdwAllocType = PVAT_SYSALLOC ;
  128.             break ;
  129.         case VT_VECTOR | VT_UI1:
  130.             cbDataSize = PROPVARIANT_VECTOR_SIZE( caub ) ;
  131.             *pdwAllocType = PVAT_COMPLEX ;
  132.             break ;
  133.         case VT_VECTOR | VT_I2:
  134.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cai ) ;
  135.             *pdwAllocType = PVAT_COMPLEX ;
  136.             break ;
  137.         case VT_VECTOR | VT_UI2:
  138.             cbDataSize = PROPVARIANT_VECTOR_SIZE( caui ) ;
  139.             *pdwAllocType = PVAT_COMPLEX ;
  140.             break ;
  141.         case VT_VECTOR | VT_I4:
  142.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cal ) ;
  143.             *pdwAllocType = PVAT_COMPLEX ;
  144.             break ;
  145.         case VT_VECTOR | VT_UI4:
  146.             cbDataSize = PROPVARIANT_VECTOR_SIZE( caul ) ;
  147.             *pdwAllocType = PVAT_COMPLEX ;
  148.             break ;
  149.         case VT_VECTOR | VT_I8:
  150.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cah ) ;
  151.             *pdwAllocType = PVAT_COMPLEX ;
  152.             break ;
  153.         case VT_VECTOR | VT_UI8:
  154.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cauh ) ;
  155.             *pdwAllocType = PVAT_COMPLEX ;
  156.             break ;
  157.         case VT_VECTOR | VT_R4:
  158.             cbDataSize = PROPVARIANT_VECTOR_SIZE( caflt ) ;
  159.             *pdwAllocType = PVAT_COMPLEX ;
  160.             break ;
  161.         case VT_VECTOR | VT_R8:
  162.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cadbl ) ;
  163.             *pdwAllocType = PVAT_COMPLEX ;
  164.             break ;
  165.         case VT_VECTOR | VT_CY:
  166.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cacy ) ;
  167.             *pdwAllocType = PVAT_COMPLEX ;
  168.             break ;
  169.         case VT_VECTOR | VT_DATE:
  170.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cadate ) ;
  171.             *pdwAllocType = PVAT_COMPLEX ;
  172.             break ;
  173.         case VT_VECTOR | VT_BOOL:
  174.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cabool ) ;
  175.             *pdwAllocType = PVAT_COMPLEX ;
  176.             break ;
  177.         case VT_VECTOR | VT_ERROR:
  178.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cascode ) ;
  179.             *pdwAllocType = PVAT_COMPLEX ;
  180.             break ;
  181.         case VT_VECTOR | VT_FILETIME:
  182.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cafiletime ) ;
  183.             *pdwAllocType = PVAT_COMPLEX ;
  184.             break ;
  185.         case VT_VECTOR | VT_CLSID:
  186.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cauuid ) ;
  187.             *pdwAllocType = PVAT_COMPLEX ;
  188.             break ;
  189.         case VT_VECTOR | VT_BSTR:
  190.             cbDataSize = PROPVARIANT_VECTOR_SIZE( cabstr ) ;
  191.             for( i=0; i < var.cabstr.cElems; i++ )
  192.                 cbDataSize += ((var.cabstr.pElems[i]==NULL) ? lstrlenW( var.cabstr.pElems[i] ) + 1 : 0) ;
  193.             *pdwAllocType = PVAT_COMPLEX ;
  194.             break ;
  195.         case VT_VECTOR | VT_LPSTR:
  196.             cbDataSize = PROPVARIANT_VECTOR_SIZE( calpstr ) ;
  197.             for( i=0; i < var.calpstr.cElems; i++ )
  198.                 cbDataSize += ((var.calpstr.pElems[i]==NULL) ? lstrlenA( var.calpstr.pElems[i] ) + 1 : 0) ;
  199.             *pdwAllocType = PVAT_COMPLEX ;
  200.             break ;
  201.         case VT_VECTOR | VT_LPWSTR:
  202.             cbDataSize = PROPVARIANT_VECTOR_SIZE( calpwstr ) ;
  203.             for( i=0; i < var.calpwstr.cElems; i++ )
  204.                 cbDataSize += ((var.calpwstr.pElems[i]==NULL) ? lstrlenW( var.calpwstr.pElems[i] ) + 1 : 0) ;
  205.             *pdwAllocType = PVAT_COMPLEX ;
  206.             break ;
  207.         case VT_VECTOR | VT_CF:
  208.             //caclipdata; 
  209.         case VT_VECTOR | VT_VARIANT:
  210.             //capropvar;  
  211.             *pdwAllocType = PVAT_COMPLEX ;
  212.             hr = E_NOTIMPL ;
  213.             break ;
  214.         case VT_STREAM:
  215.         case VT_STORAGE:
  216.             *pdwAllocType = PVAT_SYSALLOC ;
  217.             hr = E_NOTIMPL ;
  218.             break ;
  219.         default:
  220.             return E_UNEXPECTED ;
  221.     }
  222.     return hr ;
  223. }
  224. //-------------------------------------------------------------------------//
  225. //  Writes the data contained by a PROPVARIANT instance to single, contiguous 
  226. //  memory buffer.
  227. HRESULT PropVariantWriteMem( IN const PROPVARIANT& var, OUT BYTE* pBuf, IN ULONG cbBuf )
  228. {
  229.     HRESULT hr ;
  230.     
  231.     #define PROPVARIANT_TYPECAST_COPY( buf, cbBuf, type, member ) 
  232.                 { if( cbBuf < sizeof(type) ) return E_OUTOFMEMORY ; 
  233.                   (*((type*)buf)) = var.member ; 
  234.                   buf   += sizeof(var.member) ; 
  235.                   cbBuf -= sizeof(var.member) ; } 
  236.     ULONG   cbDataSize = 0, 
  237.             cb ;            // scratch
  238.     
  239.     if( !SUCCEEDED( (hr = PropVariantSize( var, cbDataSize, NULL )) ) )
  240.         return hr ;
  241.     //  Ensure cbBuf is large enough to contain the data
  242.     if( cbDataSize + sizeof(VARTYPE) > cbBuf )
  243.     {
  244.         ASSERT( FALSE ) ;
  245.         return E_OUTOFMEMORY ;
  246.     }
  247.     //  Copy vartype
  248.     PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, VARTYPE, vt ) ;
  249.     hr = S_OK ;
  250.     
  251.     switch( var.vt )
  252.     {
  253.         case VT_EMPTY:
  254.         case VT_NULL:
  255.         case VT_ILLEGAL:
  256.             break ;
  257.                         
  258.         case VT_UI1:
  259.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, UCHAR, bVal ) ;
  260.             break ;
  261.         case VT_I2:
  262.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, SHORT, iVal ) ;
  263.             break ;
  264.         case VT_UI2:
  265.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, USHORT, uiVal ) ;
  266.             break ;
  267.             
  268.         case VT_BOOL:
  269.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, VARIANT_BOOL, boolVal ) ;
  270.             break ;
  271.         case VT_I4:
  272.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, long, lVal) ;
  273.             break ;
  274.  
  275.         case VT_UI4:
  276.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, ULONG, ulVal) ;
  277.             break ;
  278.         case VT_R4:
  279.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, float, fltVal) ;
  280.             break ;
  281.         case VT_ERROR:
  282.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, SCODE, scode) ;
  283.             break ;
  284.         case VT_I8:
  285.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, LARGE_INTEGER, hVal) ;
  286.             break ;
  287.         case VT_UI8:
  288.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, ULARGE_INTEGER, uhVal) ;
  289.         case VT_R8:
  290.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, double, dblVal) ;
  291.             break ;
  292.         case VT_CY:
  293.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, CY, cyVal) ;
  294.             break ;
  295.         case VT_DATE:
  296.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, DATE, date) ;
  297.             break ;
  298.         case VT_FILETIME:
  299.             PROPVARIANT_TYPECAST_COPY( pBuf, cbBuf, FILETIME, filetime) ;
  300.             break ;
  301.         
  302.         case VT_CLSID:
  303.             cbBuf = min( cbBuf, sizeof(*var.puuid) ) ;
  304.             memcpy( pBuf, var.puuid, cbBuf ) ;
  305.             break ;
  306.         case VT_BSTR:
  307.             cb = min( cbBuf-1, lstrlenW( var.bstrVal )*sizeof(WCHAR) ) ;
  308.             lstrcpynW( (WCHAR*)pBuf, var.bstrVal, cb+1 ) ;
  309.             cbBuf -= (cb + 1) ;
  310.             break ;
  311.         case VT_LPSTR:
  312.             cb = min( cbBuf-1, lstrlenA( var.pszVal )*sizeof(CHAR) ) ;
  313.             lstrcpynA( (CHAR*)pBuf, var.pszVal, cb+1 ) ;
  314.             cbBuf -= (cb + 1) ;
  315.             break ;
  316.             
  317.         case VT_LPWSTR:
  318.             cb = min( cbBuf-1, lstrlenW( var.pwszVal )*sizeof(WCHAR) ) ;
  319.             lstrcpynW( (WCHAR*)pBuf, var.pwszVal, cb+1 ) ;
  320.             cbBuf -= (cb + 1) ;
  321.             break ;
  322.         case VT_BLOB:
  323.         case VT_CF :
  324.         case VT_VECTOR | VT_UI1:
  325.         case VT_VECTOR | VT_I2:
  326.         case VT_VECTOR | VT_UI2:
  327.         case VT_VECTOR | VT_I4:
  328.         case VT_VECTOR | VT_UI4:
  329.         case VT_VECTOR | VT_I8:
  330.         case VT_VECTOR | VT_UI8:
  331.         case VT_VECTOR | VT_R4:
  332.         case VT_VECTOR | VT_R8:
  333.         case VT_VECTOR | VT_CY:
  334.         case VT_VECTOR | VT_DATE:
  335.         case VT_VECTOR | VT_BOOL:
  336.         case VT_VECTOR | VT_ERROR:
  337.         case VT_VECTOR | VT_FILETIME:
  338.         case VT_VECTOR | VT_BSTR:
  339.         case VT_VECTOR | VT_LPSTR:
  340.         case VT_VECTOR | VT_LPWSTR:
  341.         case VT_VECTOR | VT_CLSID:
  342.         case VT_VECTOR | VT_CF:
  343.         case VT_VECTOR | VT_VARIANT:
  344.         case VT_STREAM:
  345.         case VT_STORAGE:
  346.             hr = E_NOTIMPL ;
  347.             break ;
  348.         default:
  349.             hr = E_UNEXPECTED ;
  350.     }
  351.     return hr ;
  352. }
  353. //-------------------------------------------------------------------------//
  354. //  Reads the data contained by a PROPVARIANT instance to single, contiguous 
  355. //  memory buffer.
  356. HRESULT PropVariantReadMem( IN BYTE* pBuf, OUT PROPVARIANT& var )
  357. {
  358.     HRESULT     hr = S_OK ;
  359.     PROPVARIANT varTmp ;
  360.     
  361.     PropVariantInit( &var ) ;
  362.     PropVariantInit( &varTmp ) ;
  363.     if( !pBuf ) return E_POINTER ;
  364.     #define PROPVARIANT_TYPECAST_ASSIGN( buf, type, val ) 
  365.         { varTmp.val = *((type*)buf) ; buf += sizeof(type) ; }
  366.     //  Determine type
  367.     PROPVARIANT_TYPECAST_ASSIGN( pBuf, VARTYPE, vt ) ;
  368.     switch( varTmp.vt )
  369.     {
  370.         case VT_EMPTY:
  371.         case VT_NULL:
  372.         case VT_ILLEGAL:
  373.             break ;
  374.                         
  375.         case VT_UI1:
  376.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, UCHAR, bVal ) ;
  377.             break ;
  378.         case VT_I2:
  379.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, SHORT, iVal ) ;
  380.             break ;
  381.         case VT_UI2:
  382.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, USHORT, uiVal ) ;
  383.             break ;
  384.             
  385.         case VT_BOOL:
  386.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, VARIANT_BOOL, boolVal ) ;
  387.             break ;
  388.         case VT_I4:
  389.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, long, lVal) ;
  390.             break ;
  391.  
  392.         case VT_UI4:
  393.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, ULONG, ulVal) ;
  394.             break ;
  395.         case VT_R4:
  396.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, float, fltVal) ;
  397.             break ;
  398.         case VT_ERROR:
  399.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, SCODE, scode) ;
  400.             break ;
  401.         case VT_I8:
  402.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, LARGE_INTEGER, hVal) ;
  403.             break ;
  404.         case VT_UI8:
  405.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, ULARGE_INTEGER, uhVal) ;
  406.         case VT_R8:
  407.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, double, dblVal) ;
  408.             break ;
  409.         case VT_CY:
  410.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, CY, cyVal) ;
  411.             break ;
  412.         case VT_DATE:
  413.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, DATE, date) ;
  414.             break ;
  415.         case VT_FILETIME:
  416.             PROPVARIANT_TYPECAST_ASSIGN( pBuf, FILETIME, filetime) ;
  417.             break ;
  418.         
  419.         case VT_CLSID:
  420.             varTmp.puuid = (CLSID*)pBuf ;
  421.             break ;
  422.         case VT_BSTR:
  423.             varTmp.bstrVal = (BSTR)pBuf ;
  424.             break ;
  425.         case VT_LPSTR:
  426.             varTmp.pszVal = (LPSTR)pBuf ;
  427.             break ;
  428.             
  429.         case VT_LPWSTR:
  430.             varTmp.pwszVal = (LPWSTR)pBuf ;
  431.             break ;
  432.         case VT_BLOB:
  433.         case VT_CF :
  434.         case VT_VECTOR | VT_UI1:
  435.         case VT_VECTOR | VT_I2:
  436.         case VT_VECTOR | VT_UI2:
  437.         case VT_VECTOR | VT_I4:
  438.         case VT_VECTOR | VT_UI4:
  439.         case VT_VECTOR | VT_I8:
  440.         case VT_VECTOR | VT_UI8:
  441.         case VT_VECTOR | VT_R4:
  442.         case VT_VECTOR | VT_R8:
  443.         case VT_VECTOR | VT_CY:
  444.         case VT_VECTOR | VT_DATE:
  445.         case VT_VECTOR | VT_BOOL:
  446.         case VT_VECTOR | VT_ERROR:
  447.         case VT_VECTOR | VT_FILETIME:
  448.         case VT_VECTOR | VT_BSTR:
  449.         case VT_VECTOR | VT_LPSTR:
  450.         case VT_VECTOR | VT_LPWSTR:
  451.         case VT_VECTOR | VT_CLSID:
  452.         case VT_VECTOR | VT_CF:
  453.         case VT_VECTOR | VT_VARIANT:
  454.         case VT_STREAM:
  455.         case VT_STORAGE:
  456.             hr = E_NOTIMPL ;
  457.             break ;
  458.         default:
  459.             hr = E_UNEXPECTED ;
  460.     }
  461.     if( SUCCEEDED( hr ) )
  462.         ::PropVariantCopy( &var, &varTmp ) ;
  463.     return hr ;
  464. }
  465. //-------------------------------------------------------------------------//
  466. HRESULT PropVariantToBstr( const PROPVARIANT* pvar, UINT nCodePage, ULONG dwFlags, LPCTSTR pszFmt, OUT BSTR* pbstrText )
  467. {
  468.     ASSERT( pvar ) ;
  469.     ASSERT( pbstrText ) ;
  470.     HRESULT     hr = E_FAIL ;
  471.     LCID        lcid = GetUserDefaultLCID() ;
  472.     const DWORD cchNumBuf   = 32 ;
  473.     
  474.     UNREFERENCED_PARAMETER( pszFmt ) ;
  475.     USES_CONVERSION ;
  476.     *pbstrText = NULL ;
  477.     switch( pvar->vt )
  478.     {
  479.         case VT_EMPTY:
  480.         case VT_NULL:
  481.         case VT_ILLEGAL:
  482.             *pbstrText = SysAllocString( L"" ) ;
  483.             return S_OK ;   // return blank
  484.         case VT_UI1:
  485.             return VarBstrFromUI1( pvar->bVal, lcid, dwFlags, pbstrText ) ;
  486.         case VT_I2:
  487.             return VarBstrFromI2( pvar->iVal, lcid, dwFlags, pbstrText ) ;
  488.         case VT_UI2:
  489.             return VarBstrFromUI2(  pvar->uiVal, lcid, dwFlags, pbstrText );
  490.             
  491.         case VT_BOOL:
  492.             return VarBstrFromBool( pvar->boolVal, lcid, dwFlags, pbstrText ) ;
  493.         case VT_I4:
  494.             return VarBstrFromI4( pvar->lVal, lcid, dwFlags, pbstrText ) ;
  495.  
  496.         case VT_UI4:
  497.             return VarBstrFromUI4( pvar->ulVal, lcid, dwFlags, pbstrText );
  498.         case VT_R4:
  499.             return VarBstrFromR4( pvar->fltVal, lcid, dwFlags, pbstrText ) ;
  500.         case VT_ERROR:
  501.             return VarBstrFromUI4( pvar->scode, lcid, dwFlags, pbstrText );
  502.         case VT_I8:
  503.         case VT_UI8:
  504.             if( (*pbstrText = SysAllocStringLen( NULL, cchNumBuf ))!=NULL )
  505.             {
  506.                 if( pvar->vt==VT_I8 ? _i64tow( pvar->hVal.QuadPart, *pbstrText, 10 )!=NULL :
  507.                                     _ui64tow( pvar->hVal.QuadPart, *pbstrText, 10 )!=NULL )
  508.                     return TRUE ;
  509.                 SysFreeString( *pbstrText ) ;
  510.                 *pbstrText = NULL ;
  511.             }
  512.             break ; 
  513.         case VT_R8:
  514.             return VarBstrFromR8( pvar->dblVal, lcid, dwFlags, pbstrText ) ;
  515.         case VT_CY:
  516.             return VarBstrFromCy( pvar->cyVal, lcid, dwFlags , pbstrText ) ;
  517.         case VT_DATE:
  518.             return VarBstrFromDate( pvar->date, lcid, VAR_DATEVALUEONLY, pbstrText ) ;
  519.         case VT_FILETIME:
  520.         {
  521.             SYSTEMTIME  st ;
  522.             DATE        d ;
  523.             if( pvar->filetime.dwLowDateTime == 0L &&
  524.                 pvar->filetime.dwHighDateTime ==0L )
  525.             {
  526.                 *pbstrText = SysAllocString( L"" ) ;
  527.                 return S_OK ;
  528.             }
  529.             if( FileTimeToSystemTime( &pvar->filetime, &st ) &&
  530.                 SystemTimeToVariantTime( &st, &d ) )
  531.             {
  532.                 return VarBstrFromDate( d, lcid, VAR_DATEVALUEONLY, pbstrText ) ;
  533.             }
  534.             break ;
  535.         }
  536.         
  537.         case VT_CLSID:
  538.             if( pvar->puuid )
  539.             {
  540.                 LPWSTR pwsz = NULL ;
  541.                 //  Note: we can't hand back this directly, because the
  542.                 //  caller expects a BSTR that should be freed with SysFreeString.
  543.                 if( SUCCEEDED( (hr = StringFromCLSID( *pvar->puuid, &pwsz )) ) )
  544.                 {
  545.                     *pbstrText = SysAllocString( pwsz ) ;
  546.                     CoTaskMemFree( pwsz ) ; // free intermediate buffer.
  547.                     if( *pbstrText ) 
  548.                         return S_OK ;
  549.                     break ;
  550.                 }
  551.             }
  552.             else
  553.             {
  554.                 if( (*pbstrText = SysAllocString( L"" ))!=NULL )
  555.                     return S_OK ;
  556.             }
  557.             break ;
  558.         case VT_BLOB:
  559.             if( pvar->blob.pBlobData != NULL )
  560.                 *pbstrText = SysAllocString( L"..." ) ;
  561.             else
  562.                 *pbstrText = SysAllocString( L"" ) ;
  563.             return S_OK ;
  564.         case VT_CF :
  565.         {
  566.             long cf = 0 ;
  567.             
  568.             if( pvar->pclipdata ) 
  569.                 cf = pvar->pclipdata->ulClipFmt ;
  570.             if( cf > 0 )
  571.             {
  572.                 if( (*pbstrText = SysAllocString( clipformats[cf-1] ))!=NULL )
  573.                     return S_OK ;
  574.             }
  575.             break ;
  576.         }
  577.         case VT_BSTR:
  578.             if( (*pbstrText = SysAllocString( pvar->bstrVal ? pvar->bstrVal : L"" ))!=NULL )
  579.                 return S_OK ;
  580.             break ;
  581.         case VT_LPSTR:
  582.             if( (*pbstrText = SysAllocString( pvar->pszVal ? A2W( pvar->pszVal ) : L"" )) != NULL )
  583.                 return S_OK ;
  584.             break ;
  585.             
  586.         case VT_LPWSTR:
  587.             if( (*pbstrText = SysAllocString( pvar->pwszVal ? pvar->pwszVal : L"" )) != NULL )
  588.                 return S_OK ;
  589.             break ;
  590.         case VT_VECTOR | VT_UI1:
  591.             //pvar->caub;     
  592.         case VT_VECTOR | VT_I2:
  593.             //pvar->cai;      
  594.         case VT_VECTOR | VT_UI2:
  595.             //pvar->caui;     
  596.         case VT_VECTOR | VT_I4:
  597.             //pvar->cal;      
  598.         case VT_VECTOR | VT_UI4:
  599.             //pvar->caul;     
  600.         case VT_VECTOR | VT_I8:
  601.             //pvar->cah;      
  602.         case VT_VECTOR | VT_UI8:
  603.             //pvar->cauh;     
  604.         case VT_VECTOR | VT_R4:
  605.             //pvar->caflt;    
  606.         case VT_VECTOR | VT_R8:
  607.             //pvar->cadbl;    
  608.         case VT_VECTOR | VT_CY:
  609.             //pvar->cacy;     
  610.         case VT_VECTOR | VT_DATE:
  611.             //pvar->cadate;   
  612.         case VT_VECTOR | VT_BSTR:
  613.             //pvar->cabstr;   
  614.         case VT_VECTOR | VT_BOOL:
  615.             //pvar->cabool;   
  616.         case VT_VECTOR | VT_ERROR:
  617.             //pvar->cascode;  
  618.         case VT_VECTOR | VT_LPSTR:
  619.             //pvar->calpstr;  
  620.         case VT_VECTOR | VT_LPWSTR:
  621.             //pvar->calpwstr; 
  622.         case VT_VECTOR | VT_FILETIME:
  623.             //pvar->cafiletime; 
  624.         case VT_VECTOR | VT_CLSID:
  625.             //pvar->cauuid;     
  626.         case VT_VECTOR | VT_CF:
  627.             //pvar->caclipdata; 
  628.         case VT_VECTOR | VT_VARIANT:
  629.             //pvar->capropvar;  
  630.             return E_NOTIMPL ;
  631.         //  Unsupported types
  632.         case VT_STREAM:
  633.         case VT_STORAGE:
  634.             return E_NOTIMPL ;
  635.         //  Illegal types for OLE properties
  636.         default:
  637.             return ERROR_INVALID_DATA ;
  638.     }
  639.     return hr ;
  640. }
  641. //-------------------------------------------------------------------------//
  642. HRESULT PropVariantToString( const PROPVARIANT* pvar, UINT nCodePage, ULONG dwFlags, LPCTSTR pszFmt, OUT LPTSTR pszText, IN ULONG cchTextMax )
  643. {
  644.     BSTR    bstrText = NULL ;
  645.     HRESULT hr = PropVariantToBstr( pvar, nCodePage, dwFlags, pszFmt, &bstrText ) ;
  646.     if( SUCCEEDED( hr ) )
  647.     {
  648.         lstrcpyn( pszText, W2T( bstrText ), cchTextMax ) ;
  649.         SysFreeString( bstrText ) ;
  650.     }
  651.     return hr ;
  652. }
  653. //-------------------------------------------------------------------------//
  654. HRESULT PropVariantFromBstr( 
  655.     IN const BSTR bstrText, 
  656.     IN UINT nCodePage, 
  657.     IN ULONG dwFlags, 
  658.     IN LPCTSTR pszFmt, 
  659.     OUT PROPVARIANT* pvar )
  660. {
  661.     UNREFERENCED_PARAMETER( pszFmt ) ;
  662.     ASSERT( pvar ) ;
  663.     HRESULT     hr = E_FAIL ;
  664.     LCID        lcid = GetUserDefaultLCID() ;
  665.     VARTYPE     vtSave = pvar->vt ;
  666.     if( !( bstrText && *bstrText ) )
  667.     {
  668.         //  We're being passed an empty string, so simply zero out
  669.         //  and restore the current VARTYPE.
  670.         PropVariantClear( pvar ) ;
  671.         pvar->vt = vtSave ;
  672.         return S_OK ;
  673.     }
  674.     
  675.     USES_CONVERSION ;
  676.     switch( vtSave )
  677.     {
  678.         case VT_EMPTY:
  679.         case VT_NULL:
  680.         case VT_ILLEGAL:
  681.             // Clear ourselves always.
  682.             PropVariantClear( pvar ) ;
  683.             pvar->vt = vtSave ;
  684.             return S_OK ;   
  685.         case VT_UI1:
  686.             hr = VarUI1FromStr( bstrText, lcid, dwFlags, &pvar->bVal ) ;
  687.             break ;
  688.         case VT_I2:
  689.             hr = VarI2FromStr( bstrText, lcid, dwFlags, &pvar->iVal ) ;
  690.             break ;
  691.         case VT_UI2:
  692.             hr = VarUI2FromStr(  bstrText, lcid, dwFlags, &pvar->uiVal ) ;
  693.             break ;
  694.             
  695.         case VT_BOOL:
  696.             hr = VarBoolFromStr( bstrText, lcid, dwFlags, &pvar->boolVal ) ;
  697.             break ;
  698.         case VT_I4:
  699.             hr = VarI4FromStr( bstrText, lcid, dwFlags, &pvar->lVal ) ;
  700.             break ;
  701.  
  702.         case VT_UI4:
  703.             hr = VarUI4FromStr(  bstrText, lcid, dwFlags, &pvar->ulVal ) ;
  704.             {
  705.             }
  706.             break ;
  707.         case VT_R4:
  708.             if( SUCCEEDED( (hr = VarR4FromStr( bstrText, lcid, dwFlags, &pvar->fltVal )) ) )
  709.             {
  710.             }
  711.             break ;
  712.         case VT_ERROR:
  713.             if( SUCCEEDED( (hr = VarI4FromStr( bstrText, lcid, dwFlags, &pvar->scode )) ) )
  714.             {
  715.             }
  716.             break ;
  717.         //case VT_I8:
  718.         //    return _i64tot( hVal.QuadPart, pszBuf, 10 ) ; 
  719.         //case VT_UI8:
  720.         //    return _ui64tot( hVal.QuadPart, pszBuf, 10 ) ; 
  721.         case VT_R8:
  722.             if( SUCCEEDED( (hr = VarR8FromStr( bstrText, lcid, dwFlags, &pvar->dblVal )) ) )
  723.             {
  724.             }
  725.             break ;
  726.         case VT_CY:
  727.             if( SUCCEEDED( (hr = VarCyFromStr( bstrText, lcid, dwFlags , &pvar->cyVal )) ) )
  728.             {
  729.             }
  730.             break ;
  731.         case VT_DATE:
  732.             if( SUCCEEDED( (hr = VarDateFromStr( bstrText, lcid, VAR_DATEVALUEONLY, &pvar->date )) ) )
  733.             {
  734.             }
  735.             break ;
  736.         case VT_FILETIME:
  737.         {
  738.             FILETIME    ft ;
  739.             SYSTEMTIME  st ;
  740.             DATE        d ;
  741.             if( bstrText && *bstrText )
  742.             {
  743.                 if( SUCCEEDED( (hr = VarDateFromStr( bstrText, lcid, VAR_DATEVALUEONLY, &d )) ) &&
  744.                     VariantTimeToSystemTime( d, &st ) &&
  745.                     SystemTimeToFileTime( &st, &ft ) )
  746.                 {
  747.                     pvar->filetime = ft ;
  748.                     return S_OK ;
  749.                 }
  750.             }
  751.             else
  752.             {
  753.                 memset( &pvar->filetime, 0, sizeof(pvar->filetime) ) ;
  754.                 return S_OK ;
  755.             }
  756.             break ;
  757.         }
  758.         
  759.         case VT_CLSID:
  760.             {
  761.                 CLSID clsid ;
  762.                 if( SUCCEEDED( (hr = CLSIDFromString( bstrText, &clsid )) ) )
  763.                 {
  764.                     PropVariantClear( pvar ) ;
  765.                     if( NULL == (pvar->puuid = (CLSID*)CoTaskMemAlloc( sizeof(clsid) )) )
  766.                         return E_OUTOFMEMORY ;
  767.                     *pvar->puuid = clsid ;
  768.                     pvar->vt = vtSave ;
  769.                     return S_OK ;
  770.                 }
  771.             }
  772.             break ;
  773.         case VT_BSTR:
  774.             PropVariantClear( pvar ) ;
  775.             pvar->bstrVal = SysAllocString( bstrText ) ;
  776.             pvar->vt = vtSave ;
  777.             return S_OK ;
  778.         case VT_LPSTR:
  779.         {
  780.             PropVariantClear( pvar ) ;
  781.             int cb = sizeof(CHAR) * (lstrlenA( W2A(bstrText) ) + 1) ;
  782.             if( NULL == (pvar->pszVal = (LPSTR)CoTaskMemAlloc( cb )) )
  783.                 return E_OUTOFMEMORY ;
  784.             memcpy( pvar->pszVal, W2A( bstrText ), cb ) ;
  785.             pvar->vt = vtSave ;
  786.             return S_OK ;
  787.         }
  788.             
  789.         case VT_LPWSTR:
  790.         {
  791.             PropVariantClear( pvar ) ;
  792.             int cb = sizeof(WCHAR) * (lstrlenW( bstrText ) + 1) ;
  793.             if( NULL == (pvar->pwszVal = (LPWSTR)CoTaskMemAlloc( cb )) )
  794.                 return E_OUTOFMEMORY ;
  795.             memcpy( pvar->pwszVal, bstrText, cb ) ;
  796.             pvar->vt = vtSave ;
  797.             return S_OK ;
  798.         }
  799.         case VT_VECTOR | VT_UI1:
  800.             //pvar->caub;     
  801.         case VT_VECTOR | VT_I2:
  802.             //pvar->cai;      
  803.         case VT_VECTOR | VT_UI2:
  804.             //pvar->caui;     
  805.         case VT_VECTOR | VT_I4:
  806.             //pvar->cal;      
  807.         case VT_VECTOR | VT_UI4:
  808.             //pvar->caul;     
  809.         case VT_VECTOR | VT_I8:
  810.             //pvar->cah;      
  811.         case VT_VECTOR | VT_UI8:
  812.             //pvar->cauh;     
  813.         case VT_VECTOR | VT_R4:
  814.             //pvar->caflt;    
  815.         case VT_VECTOR | VT_R8:
  816.             //pvar->cadbl;    
  817.         case VT_VECTOR | VT_CY:
  818.             //pvar->cacy;     
  819.         case VT_VECTOR | VT_DATE:
  820.             //pvar->cadate;   
  821.         case VT_VECTOR | VT_BSTR:
  822.             //pvar->cabstr;   
  823.         case VT_VECTOR | VT_BOOL:
  824.             //pvar->cabool;   
  825.         case VT_VECTOR | VT_ERROR:
  826.             //pvar->cascode;  
  827.         case VT_VECTOR | VT_LPSTR:
  828.             //pvar->calpstr;  
  829.         case VT_VECTOR | VT_LPWSTR:
  830.             //pvar->calpwstr; 
  831.         case VT_VECTOR | VT_FILETIME:
  832.             //pvar->cafiletime; 
  833.         case VT_VECTOR | VT_CLSID:
  834.             //pvar->cauuid;     
  835.         case VT_VECTOR | VT_CF:
  836.             //pvar->caclipdata; 
  837.         case VT_VECTOR | VT_VARIANT:
  838.             //pvar->capropvar;  
  839.             return E_NOTIMPL ;
  840.         //  Illegal types for which to assign value from display text.
  841.         case VT_BLOB:
  842.         case VT_CF :
  843.         case VT_STREAM:
  844.         case VT_STORAGE:
  845.             return E_INVALIDARG ;
  846.         //  Illegal types for OLE properties
  847.         default:
  848.             return ERROR_INVALID_DATA ;
  849.     }
  850.     return hr ;
  851. }
  852. //-------------------------------------------------------------------------//
  853. HRESULT PropVariantFromString( 
  854.     IN LPCTSTR pszText, 
  855.     IN UINT nCodePage, 
  856.     IN ULONG dwFlags, 
  857.     IN LPCTSTR pszFmt, 
  858.     OUT PROPVARIANT* pvar )
  859. {
  860.     HRESULT hr = E_FAIL ;
  861.     BSTR    bstrText = NULL ;
  862.     USES_CONVERSION ; 
  863.     if( pszText )
  864.         if( (bstrText = SysAllocString( T2W( (LPTSTR)pszText ) )) == NULL )
  865.             return E_OUTOFMEMORY ;
  866.     hr = PropVariantFromBstr( bstrText, nCodePage, dwFlags, pszFmt, pvar ) ;
  867.     
  868.     if( bstrText )
  869.         SysFreeString( bstrText ) ;
  870.     return hr ;
  871. }
  872. //-------------------------------------------------------------------------//
  873. //  Generates a 32-bit hash value for the contents of a PROPVARIANT instance.
  874. HRESULT PropVariantHash( IN const PROPVARIANT& var, OUT ULONG& dwHash )
  875. {
  876.     HRESULT     hr ;
  877.     ULONG       cbVar = 0 ;
  878.     const BYTE* pVar = NULL ;
  879.     
  880.     dwHash = var.vt ;
  881.     if( !SUCCEEDED( (hr = PropVariantSize( var, cbVar, NULL )) ) )
  882.         return hr ;
  883.     switch( var.vt )
  884.     {
  885.         case VT_EMPTY:
  886.         case VT_NULL:
  887.         case VT_ILLEGAL:
  888.             break ;
  889.         case VT_I1:
  890.         case VT_UI1:
  891.         case VT_I2:
  892.         case VT_UI2:
  893.         case VT_I4:
  894.         case VT_UI4:
  895.         case VT_I8:
  896.         case VT_UI8:
  897.         case VT_R4:
  898.         case VT_R8:
  899.         case VT_CY:
  900.         case VT_DATE:
  901.         case VT_ERROR:
  902.         case VT_BOOL:
  903.         case VT_INT:
  904.         case VT_FILETIME:
  905.             pVar = &var.bVal ; break ;
  906.         case VT_BSTR:
  907.             pVar = (const BYTE*)var.bstrVal ;  break ;
  908.         case VT_CLSID:
  909.             pVar = (const BYTE*)var.puuid ;    break ;
  910.         case VT_LPSTR:
  911.             pVar = (const BYTE*)var.pszVal ;   break ;
  912.         case VT_LPWSTR:
  913.             pVar = (const BYTE*)var.pwszVal ;  break ;
  914.         case VT_CF:
  915.         case VT_BLOB:
  916.         case VT_DISPATCH:
  917.         case VT_STREAM:
  918.         case VT_STORAGE:
  919.         case VT_STREAMED_OBJECT:
  920.         case VT_STORED_OBJECT:
  921.         case VT_BLOB_OBJECT:
  922.         case VT_VECTOR | VT_UI1:
  923.             //CAUB caub;
  924.         case VT_VECTOR | VT_I2:
  925.             //CAI cai;
  926.         case VT_VECTOR | VT_UI2:
  927.             //CAUI caui;
  928.         case VT_VECTOR | VT_BOOL:
  929.             //CABOOL cabool;
  930.         case VT_VECTOR | VT_I4:
  931.             //CAL cal;
  932.         case VT_VECTOR | VT_UI4:
  933.             //CAUL caul;
  934.         case VT_VECTOR | VT_R4:
  935.             //CAFLT caflt;
  936.         case VT_VECTOR | VT_ERROR:
  937.             //CASCODE cascode;
  938.         case VT_VECTOR | VT_I8:
  939.             //CAH cah;
  940.         case VT_VECTOR | VT_UI8:
  941.             //CAUH cauh;
  942.         case VT_VECTOR | VT_R8:
  943.             //CADBL cadbl;
  944.         case VT_VECTOR | VT_CY:
  945.             //CACY cacy;
  946.         case VT_VECTOR | VT_DATE:
  947.             //CADATE cadate;
  948.         case VT_VECTOR | VT_FILETIME:
  949.             //CAFILETIME cafiletime;
  950.         case VT_VECTOR | VT_CLSID:
  951.             //CACLSID cauuid;
  952.         case VT_VECTOR | VT_BSTR:
  953.             //CABSTR cabstr;
  954.         case VT_VECTOR | VT_LPSTR:
  955.             //CALPSTR calpstr;
  956.         case VT_VECTOR | VT_LPWSTR:
  957.             //CALPWSTR calpwstr;
  958.         case VT_VECTOR | VT_CF:
  959.             //CACLIPDATA caclipdata;
  960.         case VT_VECTOR | VT_BLOB:
  961.             //CABSTRBLOB cabstrblob;
  962.         //case VT_VECTOR | :
  963.             //CAPROPVARIANT capropvar;
  964.             return E_NOTIMPL ;
  965.     }
  966.     
  967.     if( pVar )
  968.     {
  969.         for( ULONG i=0; i<cbVar; i++ )
  970.             dwHash += pVar[i] ;
  971.     }
  972.     return S_OK ;
  973. }
  974. //-------------------------------------------------------------------------//
  975. //  Writes the value of a PROPVARIANT to the registry
  976. HRESULT PropVariantWriteRegistry( HKEY hKey, LPCTSTR pszValueName, IN const PROPVARIANT& var )
  977. {
  978.     HRESULT  hr ;
  979.     DWORD    cbVal = 0 ;
  980.     LPBYTE   pBuf = NULL ;
  981.     
  982.     //  Determine size of data
  983.     if( !SUCCEEDED( (hr = ::PropVariantSize( var, cbVal, NULL )) ) )
  984.         return hr ;
  985.     //  Allocate buffer
  986.     cbVal += sizeof(VARTYPE) ;
  987.     if( (pBuf = new BYTE[cbVal])==NULL )
  988.         return E_OUTOFMEMORY ;
  989.     memset( pBuf, 0, cbVal ) ;
  990.     //  Copy to contiguous memory, write to registry.
  991.     if( SUCCEEDED( (hr = PropVariantWriteMem( var, pBuf, cbVal )) ) )
  992.     {
  993.         hr = HRESULT_FROM_WIN32( RegSetValueEx( hKey, pszValueName, 0L, REG_BINARY, 
  994.                                  pBuf, cbVal ) ) ;
  995.     }
  996.     delete [] pBuf ;
  997.     return hr ;
  998. }
  999. //-------------------------------------------------------------------------//
  1000. //  Reads the value of a PROPVARIANT from the registry
  1001. HRESULT PropVariantReadRegistry( HKEY hKey, LPCTSTR pszValueName, OUT PROPVARIANT& var )
  1002. {
  1003.     HRESULT hr ;
  1004.     ULONG   dwErr ;
  1005.     DWORD dwType = REG_BINARY,
  1006.           cbVal = sizeof(var.vt) ;
  1007.     PropVariantInit( &var ) ;
  1008.     dwErr = RegQueryValueEx( hKey, pszValueName, 0L, &dwType, (LPBYTE)&var.vt, &cbVal ) ;
  1009.     if( !SUCCEEDED( (hr = HRESULT_FROM_WIN32( dwErr )) ) )
  1010.     {
  1011.         if( dwErr == ERROR_MORE_DATA )
  1012.         {
  1013.             LPBYTE pBuf = NULL ;
  1014.             if( (pBuf = new BYTE[cbVal+1])==NULL )
  1015.                 return E_OUTOFMEMORY ;
  1016.             dwErr = RegQueryValueEx( hKey, pszValueName, 0L, &dwType, pBuf, &cbVal ) ;
  1017.             if( SUCCEEDED( (hr = HRESULT_FROM_WIN32( dwErr )) ) )
  1018.                 hr = PropVariantReadMem( pBuf, var ) ;
  1019.             delete [] pBuf ;
  1020.         }
  1021. #ifdef TRACE
  1022.         else
  1023.         {
  1024.             TRACE( TEXT("Failed to read PROPVARIANT (VARTYPE %d) from registry (%ld)n"), var.vt, dwErr ) ;
  1025.         }
  1026. #endif TRACE
  1027.     }
  1028.     return hr ;
  1029. }                           
  1030. //-------------------------------------------------------------------------//
  1031. //  Comparison helpers
  1032. #define NUMERIC_COMPARE( a, b )      (((a)>(b)) ? 1 : ((a)<(b)) ? -1 : 0)
  1033. #define POINTER_COMPARE( a, b, cb )  (((a)&&(b)) ? memcmp( (a), (b), (cb) ) : 
  1034.                                       (a) ? 1 : (b) ? -1 : 0)
  1035. inline int TEXT_COMPAREW( LPWSTR psz1, LPWSTR psz2, ULONG uFlags )
  1036. {
  1037.     if( psz1 && psz2 )
  1038.         return (uFlags & PVCF_IGNORECASE) ? lstrcmpiW( psz1, psz2 ) :
  1039.                                             lstrcmpW( psz1, psz2 );
  1040.                          
  1041.     else if( psz1 && *psz1 )
  1042.         return 1 ;
  1043.     else if( psz2 && *psz2 )
  1044.         return -1 ;
  1045.     return 0 ;
  1046. }
  1047. inline int TEXT_COMPAREA( LPSTR psz1, LPSTR psz2, ULONG uFlags )
  1048. {
  1049.     if( psz1 && psz2 )
  1050.         return (uFlags & PVCF_IGNORECASE) ? lstrcmpiA( psz1, psz2 ) :
  1051.                                             lstrcmpA( psz1, psz2 ) ;    
  1052.     else if( psz1 && *psz1 )
  1053.         return 1 ;
  1054.     else if( psz2 && *psz2 )
  1055.         return -1 ;
  1056.     return 0 ;
  1057. }
  1058. int DATETIME_COMPARE( const SYSTEMTIME* pst1, const SYSTEMTIME* pst2, ULONG uFlags )
  1059. {
  1060.     int nRet = 0;
  1061.     if( uFlags & PVCF_IGNOREDATE )
  1062.     {
  1063.         if( (nRet = NUMERIC_COMPARE( pst1->wHour, pst2->wHour )) != 0 )
  1064.             if( (nRet = NUMERIC_COMPARE( pst1->wMinute, pst2->wMinute )) == 0 )
  1065.                 if( (nRet = NUMERIC_COMPARE( pst1->wSecond, pst2->wSecond )) == 0 )
  1066.                     nRet = NUMERIC_COMPARE( pst1->wMilliseconds, pst2->wMilliseconds );
  1067.     }
  1068.     else if( uFlags & PVCF_IGNORETIME )
  1069.     {
  1070.         if( (nRet = NUMERIC_COMPARE( pst1->wYear, pst2->wYear )) == 0 )
  1071.             if( (nRet = NUMERIC_COMPARE( pst1->wMonth, pst2->wMonth )) == 0 )
  1072.                 nRet = NUMERIC_COMPARE( pst1->wDay, pst2->wDay );
  1073.     }
  1074.     else
  1075.     {
  1076.         nRet = memcmp( pst1, pst2, sizeof(*pst1) );
  1077.     }
  1078.     return nRet;
  1079. }
  1080. //-------------------------------------------------------------------------//
  1081. //  Compares the values of two PROPVARIANT instances; returns -1 if var1 is 
  1082. //  less than var2, 1 if va1 is greater than var2, and 0 if the two values
  1083. //  are equal.
  1084. int PropVariantCompare( const PROPVARIANT& var1, const PROPVARIANT& var2, ULONG uFlags )
  1085. {
  1086.     int iRet = 0 ;
  1087.     
  1088.     //  Compare VARTYPE.
  1089.     if( var1.vt != var2.vt ) 
  1090.         return NUMERIC_COMPARE( var1.vt, var2.vt ) ;
  1091.     //  Compare data
  1092.     switch( var1.vt )
  1093.     {
  1094.         case VT_EMPTY:
  1095.         case VT_NULL:
  1096.         case VT_ILLEGAL:
  1097.             return 0 ;
  1098.         case VT_UI1:
  1099.             return NUMERIC_COMPARE( var1.bVal, var2.bVal ) ;
  1100.         case VT_I2:
  1101.             return NUMERIC_COMPARE( var1.iVal, var2.iVal ) ;
  1102.         case VT_UI2:
  1103.             return NUMERIC_COMPARE( var1.uiVal, var2.uiVal );
  1104.             
  1105.         case VT_BOOL:
  1106.             return NUMERIC_COMPARE( var1.boolVal, var2.boolVal ) ;
  1107.         case VT_I4:
  1108.             return NUMERIC_COMPARE( var1.lVal, var2.lVal ) ;
  1109.  
  1110.         case VT_UI4:
  1111.             return NUMERIC_COMPARE( var1.ulVal, var2.ulVal );
  1112.         case VT_R4:
  1113.             return NUMERIC_COMPARE( var1.fltVal, var2.fltVal ) ;
  1114.         case VT_ERROR:
  1115.             return NUMERIC_COMPARE( var1.scode, var2.scode );
  1116.         case VT_I8:
  1117.             return NUMERIC_COMPARE( var1.hVal.QuadPart, var2.hVal.QuadPart ) ;
  1118.         case VT_UI8:
  1119.             return NUMERIC_COMPARE( var1.uhVal.QuadPart, var2.uhVal.QuadPart ) ;
  1120.         case VT_R8:
  1121.             return NUMERIC_COMPARE( var1.dblVal, var2.dblVal ) ;
  1122.         case VT_CY:
  1123.             return memcmp( &var1.cyVal, &var2.cyVal, sizeof(CY) ) ;
  1124.         case VT_DATE:
  1125.         {
  1126.             if( 0 == (uFlags & (PVCF_IGNOREDATE|PVCF_IGNORETIME)) )
  1127.                 return NUMERIC_COMPARE( var1.date, var2.date ) ;
  1128.             SYSTEMTIME st1, st2;
  1129.             VariantTimeToSystemTime( var1.date, &st1 );
  1130.             VariantTimeToSystemTime( var2.date, &st2 );
  1131.             return DATETIME_COMPARE( &st1, &st2, uFlags );
  1132.         }
  1133.         case VT_FILETIME:
  1134.         {
  1135.             if( 0 == (uFlags & (PVCF_IGNOREDATE|PVCF_IGNORETIME)) )
  1136.                 return memcmp( &var1.filetime, &var2.filetime, sizeof(FILETIME) ) ;
  1137.             SYSTEMTIME st1, st2;
  1138.             FileTimeToSystemTime( &var1.filetime, &st1 );
  1139.             FileTimeToSystemTime( &var2.filetime, &st2 );
  1140.             return DATETIME_COMPARE( &st1, &st2, uFlags );
  1141.         }
  1142.         
  1143.         case VT_CLSID:
  1144.             return POINTER_COMPARE( var1.puuid, var2.puuid, sizeof(CLSID) ) ;
  1145.         case VT_BLOB:
  1146.             if( (iRet = POINTER_COMPARE( var1.blob.pBlobData, var2.blob.pBlobData,
  1147.                                         min( var1.blob.cbSize, var2.blob.cbSize ) ))==0 )
  1148.                 iRet = NUMERIC_COMPARE( var1.blob.cbSize, var2.blob.cbSize ) ;
  1149.             return iRet ;
  1150.         case VT_CF :
  1151.             if( (iRet = NUMERIC_COMPARE( (DWORD_PTR)var1.pclipdata, (DWORD_PTR)var2.pclipdata ))==0 &&
  1152.                 var1.pclipdata && var2.pclipdata &&
  1153.                 (iRet = NUMERIC_COMPARE( var1.pclipdata->ulClipFmt, var2.pclipdata->ulClipFmt ))==0 &&
  1154.                 (iRet = POINTER_COMPARE( var1.pclipdata->pClipData, var2.pclipdata->pClipData,
  1155.                                          min( var1.pclipdata->cbSize, var2.pclipdata->cbSize ) ))==0 )
  1156.             {                
  1157.                 iRet = NUMERIC_COMPARE( var1.pclipdata->cbSize, var2.pclipdata->cbSize ) ;
  1158.             }
  1159.             return iRet ;
  1160.         case VT_BSTR:
  1161.             return TEXT_COMPAREW( var1.bstrVal, var2.bstrVal, uFlags ) ;
  1162.         case VT_LPSTR:
  1163.             return TEXT_COMPAREA( var1.pszVal, var2.pszVal, uFlags ) ;
  1164.             
  1165.         case VT_LPWSTR:
  1166.             return TEXT_COMPAREW( var1.pwszVal, var2.pwszVal, uFlags ) ;
  1167.         case VT_VECTOR | VT_UI1:
  1168.             //caub;     
  1169.         case VT_VECTOR | VT_I2:
  1170.             //cai;      
  1171.         case VT_VECTOR | VT_UI2:
  1172.             //caui;     
  1173.         case VT_VECTOR | VT_I4:
  1174.             //cal;      
  1175.         case VT_VECTOR | VT_UI4:
  1176.             //caul;     
  1177.         case VT_VECTOR | VT_I8:
  1178.             //cah;      
  1179.         case VT_VECTOR | VT_UI8:
  1180.             //cauh;     
  1181.         case VT_VECTOR | VT_R4:
  1182.             //caflt;    
  1183.         case VT_VECTOR | VT_R8:
  1184.             //cadbl;    
  1185.         case VT_VECTOR | VT_CY:
  1186.             //cacy;     
  1187.         case VT_VECTOR | VT_DATE:
  1188.             //cadate;   
  1189.         case VT_VECTOR | VT_BSTR:
  1190.             //cabstr;   
  1191.         case VT_VECTOR | VT_BOOL:
  1192.             //cabool;   
  1193.         case VT_VECTOR | VT_ERROR:
  1194.             //cascode;  
  1195.         case VT_VECTOR | VT_LPSTR:
  1196.             //calpstr;  
  1197.         case VT_VECTOR | VT_LPWSTR:
  1198.             //calpwstr; 
  1199.         case VT_VECTOR | VT_FILETIME:
  1200.             //cafiletime; 
  1201.         case VT_VECTOR | VT_CLSID:
  1202.             //cauuid;     
  1203.         case VT_VECTOR | VT_CF:
  1204.             //caclipdata; 
  1205.         case VT_VECTOR | VT_VARIANT:
  1206.             //capropvar;  
  1207.             break ;  //BUGBUG: Need to implement comparisons of these types.
  1208.         case VT_STREAM:
  1209.         case VT_STORAGE:
  1210.             break ;  //BUGBUG: Need to implement comparisons of these types.
  1211.     }
  1212.     return iRet ;
  1213. }
  1214. //-------------------------------------------------------------------------//
  1215. // A PROPVARIANT can hold a few more types than a VARIANT can.  We convert the types that are
  1216. // only supported by a PROPVARIANT into equivalent VARIANT types.
  1217. HRESULT PropVariantToVariant( IN const PROPVARIANT *pPropVar, OUT VARIANT *pVar)
  1218. {
  1219.     HRESULT hr = E_FAIL ;
  1220.     ASSERT(pPropVar && pVar);
  1221.     // if pVar isn't empty, this will properly free before overwriting it
  1222.     VariantClear(pVar);
  1223.     switch(pPropVar->vt)
  1224.     {
  1225.         case VT_LPSTR: 
  1226.         {
  1227.             int len = lstrlenA(pPropVar->pszVal);
  1228.             pVar->bstrVal = SysAllocStringLen(NULL, len);
  1229.             if (pVar->bstrVal)
  1230.             {
  1231.                 pVar->vt = VT_BSTR;
  1232.                 MultiByteToWideChar(CP_ACP, 0, pPropVar->pszVal, len, pVar->bstrVal, len);
  1233.                 hr = S_OK ;
  1234.             }
  1235.             break;
  1236.         }
  1237.         case VT_LPWSTR:
  1238.             pVar->bstrVal = SysAllocString(pPropVar->pwszVal);
  1239.             if (pVar->bstrVal)
  1240.             {
  1241.                 pVar->vt = VT_BSTR;
  1242.                 hr = S_OK ;
  1243.             }
  1244.             break;
  1245.         case VT_FILETIME:
  1246.         {
  1247.             SYSTEMTIME st;
  1248.             pVar->vt = VT_DATE;
  1249.             FileTimeToSystemTime(&pPropVar->filetime, &st);
  1250.             SystemTimeToVariantTime(&st, &pVar->date); // delay load...
  1251.             hr = S_OK ;
  1252.             break;
  1253.         }
  1254.         case VT_UI2:
  1255.             if (pPropVar->uiVal < 0x8000)
  1256.             {
  1257.                 pVar->vt = VT_I2;
  1258.                 pVar->iVal = (signed short) pPropVar->uiVal;
  1259.                 hr = S_OK ;
  1260.             }
  1261.             break;
  1262.         case VT_UI4:
  1263.             if (pPropVar->ulVal < 0x80000000)
  1264.             {
  1265.                 pVar->vt = VT_I4;
  1266.                 pVar->lVal = (signed int) pPropVar->ulVal;
  1267.                 hr = S_OK ;
  1268.             }
  1269.             break;
  1270.         case VT_CLSID:
  1271.             if( pPropVar->puuid )
  1272.             {
  1273.                 LPOLESTR pwszPuuid ;
  1274.                 if( SUCCEEDED( (hr = StringFromCLSID( *pPropVar->puuid, &pwszPuuid )) ) )
  1275.                 {
  1276.                     if( NULL == (pVar->bstrVal = SysAllocString( pwszPuuid )) )
  1277.                         hr = E_OUTOFMEMORY ;
  1278.                     else
  1279.                     {
  1280.                         pVar->vt = VT_BSTR;
  1281.                         hr = S_OK ;
  1282.                     }
  1283.                     CoTaskMemFree( pwszPuuid ) ;
  1284.                 }
  1285.             }
  1286.             break;
  1287.         case VT_BLOB:
  1288.         case VT_STREAM:
  1289.         case VT_STORAGE:
  1290.         case VT_BLOB_OBJECT:
  1291.         case VT_STREAMED_OBJECT:
  1292.         case VT_STORED_OBJECT:
  1293.         case VT_CF:
  1294.             ASSERT(0); // leave the output cleared
  1295.             hr = E_NOTIMPL ;
  1296.             break;
  1297.         default:
  1298.             VariantCopy(pVar, (VARIANT *)pPropVar);
  1299.             hr = S_OK ;
  1300.             break;
  1301.     }
  1302.     return hr ;
  1303. }
  1304. //-------------------------------------------------------------------------//
  1305. //  nullifies time fields in a SYSTEMTIME structure.
  1306. void SystemTimeMakeTimeless( SYSTEMTIME* pst )
  1307. {
  1308.     //  note: If the block is non-null, we set the hour to noon to avoid 
  1309.     //  date shifting across daylight savings time boundaries.
  1310.     pst->wHour = ( pst->wYear || pst->wMonth || pst->wDay ) ? 12 : 0;
  1311.     pst->wMinute = pst->wSecond = pst->wMilliseconds = 0;
  1312. }
  1313. //-------------------------------------------------------------------------//
  1314. //  nullifies time fields in a date/time propvariant.
  1315. HRESULT PropVariantMakeTimeless( PROPVARIANT* pvar )
  1316. {
  1317.     ASSERT(pvar);
  1318.     
  1319.     HRESULT     hr = S_FALSE;
  1320.     SYSTEMTIME  st;
  1321.     switch( pvar->vt )
  1322.     {
  1323.         case VT_FILETIME:
  1324.         {
  1325.             FileTimeToSystemTime( &pvar->filetime, &st );
  1326.             SystemTimeMakeTimeless( &st );
  1327.             hr = S_OK;
  1328.             SystemTimeToFileTime( &st, &pvar->filetime );
  1329.             break;
  1330.         }
  1331.         case VT_DATE:
  1332.             VariantTimeToSystemTime( pvar->date, &st );
  1333.             SystemTimeMakeTimeless( &st );
  1334.             hr = S_OK;
  1335.             SystemTimeToVariantTime( &st, &pvar->date );
  1336.             break;
  1337.     }
  1338.     return hr;
  1339. }
  1340. //-------------------------------------------------------------------------//
  1341. //  class CPropVariant : public PROPVARIANT  
  1342. //-------------------------------------------------------------------------//
  1343. //-------------------------------------------------------------------------//
  1344. HRESULT CPropVariant::GetDisplayText( 
  1345.     OUT LPTSTR pszText, 
  1346.     IN int cchText, 
  1347.     IN OPTIONAL LPCTSTR pszFmt,
  1348.     IN OPTIONAL ULONG dwFlags ) const
  1349. {
  1350.     return PropVariantToString( this, GetACP(), dwFlags, pszFmt, pszText, cchText ) ;
  1351. }
  1352. //-------------------------------------------------------------------------//
  1353. HRESULT CPropVariant::GetDisplayText( 
  1354.     OUT BSTR& bstrText,
  1355.     IN OPTIONAL LPCTSTR pszFmt,
  1356.     IN OPTIONAL ULONG dwFlags ) const
  1357. {
  1358.     return PropVariantToBstr( this, GetACP(), dwFlags, pszFmt, &bstrText ) ;
  1359. }
  1360. //-------------------------------------------------------------------------//
  1361. HRESULT CPropVariant::AssignFromDisplayText( IN LPCTSTR pszText, IN OPTIONAL LPCTSTR pszFmt )
  1362. {
  1363.     return PropVariantFromString( pszText, GetACP(), 0L, NULL, this ) ;
  1364. }
  1365. //-------------------------------------------------------------------------//
  1366. HRESULT CPropVariant::AssignFromDisplayText( IN const BSTR bstrText, IN OPTIONAL LPCTSTR pszFmt )
  1367. {
  1368.     return PropVariantFromBstr( bstrText, GetACP(), 0L, NULL, this ) ;
  1369. }
  1370. //-------------------------------------------------------------------------//
  1371. void CPropVariant::Attach( IN OUT PROPVARIANT* pSrc )
  1372. {
  1373. ASSERT( pSrc ) ;
  1374.     // Initialize ourselves
  1375.     Clear();
  1376. // Copy the source contents
  1377. memcpy( (PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT) );
  1378.     //  Empty the source and assume control of the data.
  1379. PropVariantInit( pSrc ) ;
  1380. }
  1381. //-------------------------------------------------------------------------//
  1382. void CPropVariant::Detach( OUT PROPVARIANT* pDest )
  1383. {
  1384.     ASSERT( pDest ) ;
  1385.     // Initialize the target
  1386. PropVariantClear( pDest ) ;
  1387.     // Copy out our contents and revoke control.
  1388. memcpy( pDest, this, sizeof(PROPVARIANT)) ;
  1389.     //  Initialize ourselves
  1390.     PropVariantInit( this ) ;
  1391. }
  1392. //-------------------------------------------------------------------------//
  1393. CPropVariant& CPropVariant::operator=( const CPropVariant& src )
  1394. {
  1395.     Clear() ;
  1396.     ::PropVariantCopy( this, &src ) ;   //  BUGBUG: This will leak on free.
  1397.     return *this ;
  1398. }
  1399. //-------------------------------------------------------------------------//
  1400. CPropVariant& CPropVariant::operator=( const PROPVARIANT& src )
  1401. {
  1402.     Clear() ;
  1403.     ::PropVariantCopy( this, &src ) ;   //  BUGBUG: This will leak on free.
  1404.     return *this ;
  1405. }
  1406. //-------------------------------------------------------------------------//
  1407. CPropVariant& CPropVariant::operator=( const BYTE& src )
  1408. {
  1409.     Clear() ;
  1410.     bVal = src ;
  1411.     vt = VT_UI1 ;
  1412.     return *this ;
  1413. }
  1414. //-------------------------------------------------------------------------//
  1415. CPropVariant& CPropVariant::operator=( const SHORT& src )
  1416. {
  1417.     Clear() ;
  1418.     iVal = src ;
  1419.     vt = VT_I2 ;
  1420.     return *this ;
  1421. }
  1422. //-------------------------------------------------------------------------//
  1423. CPropVariant& CPropVariant::operator=( const USHORT& src )
  1424. {
  1425.     Clear() ;
  1426.     uiVal = src ;
  1427.     vt = VT_UI2 ;
  1428.     return *this ;
  1429. }
  1430. //-------------------------------------------------------------------------//
  1431. CPropVariant& CPropVariant::operator=( const bool& src )
  1432. {
  1433.     Clear() ;
  1434. #pragma warning(disable: 4310) // cast truncates constant value
  1435.     boolVal = src ? VARIANT_TRUE : VARIANT_FALSE ;
  1436. #pragma warning(default: 4310) // cast truncates constant value
  1437.     vt = VT_BOOL ;
  1438.     return *this ;
  1439. }
  1440. //-------------------------------------------------------------------------//
  1441. CPropVariant& CPropVariant::operator=( const LONG& src )
  1442. {
  1443.     Clear() ;
  1444.     lVal = src ;
  1445.     vt = VT_I4 ;
  1446.     return *this ;
  1447. }
  1448. //-------------------------------------------------------------------------//
  1449. CPropVariant& CPropVariant::operator=( const ULONG& src )
  1450. {
  1451.     Clear() ;
  1452.     ulVal = src ;
  1453.     vt = VT_UI4 ;
  1454.     return *this ;
  1455. }
  1456. //-------------------------------------------------------------------------//
  1457. CPropVariant& CPropVariant::operator=( const FLOAT& src )
  1458. {
  1459.     Clear() ;
  1460.     fltVal = src ;
  1461.     vt = VT_R4 ;
  1462.     return *this ;
  1463. }
  1464. //-------------------------------------------------------------------------//
  1465. CPropVariant& CPropVariant::operator=( const LARGE_INTEGER& src )
  1466. {
  1467.     Clear() ;
  1468.     hVal = src ;
  1469.     vt = VT_I8 ;
  1470.     return *this ;
  1471. }
  1472. //-------------------------------------------------------------------------//
  1473. CPropVariant& CPropVariant::operator=( const ULARGE_INTEGER& src )
  1474. {
  1475.     Clear() ;
  1476.     uhVal = src ;
  1477.     vt = VT_UI8 ;
  1478.     return *this ;
  1479. }
  1480. //-------------------------------------------------------------------------//
  1481. CPropVariant& CPropVariant::operator=( const DOUBLE& src )
  1482. {
  1483.     Clear() ;
  1484.     dblVal = src ;
  1485.     vt = VT_R8 ;
  1486.     return *this ;
  1487. }
  1488. //-------------------------------------------------------------------------//
  1489. CPropVariant& CPropVariant::operator=( const CY& src )
  1490. {
  1491.     Clear() ;
  1492.     cyVal = src ;
  1493.     vt = VT_CY ;
  1494.     return *this ;
  1495. }
  1496. //-------------------------------------------------------------------------//
  1497. CPropVariant& CPropVariant::operator=( const FILETIME& src )
  1498. {
  1499.     Clear() ;
  1500.     filetime = src ;
  1501.     vt = VT_FILETIME ;
  1502.     return *this ;
  1503. }
  1504. //-------------------------------------------------------------------------//
  1505. CPropVariant& CPropVariant::operator=( const CLSID& src )
  1506. {
  1507.     Clear() ;
  1508.     if( (puuid = (CLSID*)AllocAndCopy( &src, sizeof(src) ))!=NULL )
  1509.         vt = VT_CLSID ;
  1510.     return *this ;
  1511. }
  1512. //-------------------------------------------------------------------------//
  1513. CPropVariant& CPropVariant::operator=( const BLOB& src )
  1514. {
  1515.     Clear() ;
  1516.     if( src.pBlobData != NULL && src.cbSize != 0 )
  1517.     {
  1518.         if( (blob.pBlobData = (LPBYTE)AllocAndCopy( src.pBlobData, src.cbSize ))!=NULL )
  1519.         {
  1520.             blob.cbSize = src.cbSize ;
  1521.             vt = VT_BLOB ;
  1522.         }
  1523.     }
  1524.     return *this ;
  1525. }
  1526. //-------------------------------------------------------------------------//
  1527. CPropVariant& CPropVariant::operator=( const CLIPDATA& src )
  1528. {
  1529.     Clear() ;
  1530.     if( (pclipdata = (CLIPDATA*)AllocAndCopy( &src, sizeof(src) ))!=NULL )
  1531.     {
  1532.         pclipdata->pClipData = NULL ;
  1533.         ULONG cb = src.pClipData ? CBPCLIPDATA( src ) : 0 ;
  1534.         if( cb!=0 && (pclipdata->pClipData = (LPBYTE)AllocAndCopy( src.pClipData, cb ))!=NULL )
  1535.             vt = VT_CF ;
  1536.         else
  1537.         {
  1538.             CoTaskMemFree( pclipdata ) ;
  1539.             pclipdata = NULL ;
  1540.         }
  1541.     }
  1542.     return *this ;
  1543. }
  1544. //-------------------------------------------------------------------------//
  1545. CPropVariant& CPropVariant::operator=( IStream* src )
  1546. {
  1547.     Clear() ;
  1548.     pStream = src ;
  1549.     vt = VT_STREAM ;
  1550.     return *this ;
  1551. }
  1552. //-------------------------------------------------------------------------//
  1553. CPropVariant& CPropVariant::operator=( IStorage* src )
  1554. {
  1555.     Clear() ;
  1556.     pStorage = src ;
  1557.     vt = VT_STORAGE ;
  1558.     return *this ;
  1559. }
  1560. //-------------------------------------------------------------------------//
  1561. CPropVariant& CPropVariant::operator=( const BSTR& src )
  1562. {
  1563.     Clear() ;
  1564.     if( (bstrVal = AllocString( src ))!=NULL )
  1565.         vt = VT_BSTR ;
  1566.     return *this ;
  1567. }
  1568. //-------------------------------------------------------------------------//
  1569. CPropVariant& CPropVariant::operator=( const LPSTR src )
  1570. {
  1571.     int cch ;
  1572.     
  1573.     Clear() ;
  1574.     if( src && (cch = lstrlenA( src ) + 1)> 1 )    {
  1575.         if( (pszVal = (LPSTR)AllocAndCopy( src, cch * sizeof(CHAR) ))!=NULL )
  1576.             vt = VT_LPSTR ;
  1577.     }
  1578.     return *this ;
  1579. }
  1580. //-------------------------------------------------------------------------//
  1581. CPropVariant& CPropVariant::operator=( const LPWSTR src )
  1582. {
  1583.     int cch ;
  1584.     
  1585.     Clear() ;
  1586.     if( src && (cch = lstrlenW( src ) + 1)> 1 )    {
  1587.         if( (pwszVal = (LPWSTR)AllocAndCopy( src, cch * sizeof(WCHAR) ))!=NULL )
  1588.             vt = VT_LPWSTR ;
  1589.     }
  1590.     return *this ;
  1591. }
  1592. //-------------------------------------------------------------------------//
  1593. //  Helper template function for vector type assignments
  1594. template <class CATYPE>
  1595. BOOL PropVectorAssignShallow( OUT CATYPE& caDest, OUT VARTYPE& vt, IN const CATYPE& caSrc, IN VARTYPE vtElems )
  1596. {
  1597. #pragma warning( disable : 4244 )   // conversion from 'typeA' to 'typeA', possible loss of data
  1598.     PVOID*  ppvAlloc = (PVOID*)&caDest.pElems ;
  1599.     ULONG   cb = caSrc.cElems * sizeof(*caSrc.pElems) ;
  1600.     if( ((*ppvAlloc) = CoTaskMemAlloc( cb ))!=NULL )
  1601.     {
  1602.         memcpy( caDest.pElems, caSrc.pElems, cb ) ;
  1603.         caDest.cElems = caSrc.cElems ;
  1604.         vt = VT_VECTOR|vtElems ;
  1605.         return TRUE ;
  1606.     }
  1607.     return FALSE ;
  1608. #pragma warning( default : 4244 )   // conversion from 'typeA' to 'typeA', possible loss of data
  1609. }
  1610. //-------------------------------------------------------------------------//
  1611. CPropVariant& CPropVariant::operator=( const CAUB& src )
  1612. {
  1613.     Clear() ;
  1614.     PropVectorAssignShallow( caub, vt, src, VT_UI1 ) ; 
  1615.     return *this ;
  1616. }
  1617. //-------------------------------------------------------------------------//
  1618. CPropVariant& CPropVariant::operator=( const CAI& src )
  1619. {
  1620.     Clear() ;
  1621.     PropVectorAssignShallow( cai, vt, src, VT_I2 ) ; 
  1622.     return *this ;
  1623. }
  1624. //-------------------------------------------------------------------------//
  1625. CPropVariant& CPropVariant::operator=( const CAUI& src )
  1626. {
  1627.     Clear() ;
  1628.     PropVectorAssignShallow( caui, vt, src, VT_UI2 ) ; 
  1629.     return *this ;
  1630. }
  1631. //-------------------------------------------------------------------------//
  1632. CPropVariant& CPropVariant::operator=( const CABOOL& src )
  1633. {
  1634.     Clear() ;
  1635.     PropVectorAssignShallow( cabool, vt, src, VT_BOOL ) ; 
  1636.     return *this ;
  1637. }
  1638. //-------------------------------------------------------------------------//
  1639. CPropVariant& CPropVariant::operator=( const CAL& src )
  1640. {
  1641.     Clear() ;
  1642.     PropVectorAssignShallow( cal, vt, src, VT_I4 ) ; 
  1643.     return *this ;
  1644. }
  1645. //-------------------------------------------------------------------------//
  1646. CPropVariant& CPropVariant::operator=( const CAUL& src )
  1647. {
  1648.     Clear() ;
  1649.     PropVectorAssignShallow( caul, vt, src, VT_UI4 ) ; 
  1650.     return *this ;
  1651. }
  1652. //-------------------------------------------------------------------------//
  1653. CPropVariant& CPropVariant::operator=( const CAFLT& src )
  1654. {
  1655.     Clear() ;
  1656.     PropVectorAssignShallow( caflt, vt, src, VT_R4 ) ; 
  1657.     return *this ;
  1658. }
  1659. //-------------------------------------------------------------------------//
  1660. CPropVariant& CPropVariant::operator=( const CASCODE& src )
  1661. {
  1662.     Clear() ;
  1663.     PropVectorAssignShallow( cascode, vt, src, VT_ERROR ) ; 
  1664.     return *this ;
  1665. }
  1666. //-------------------------------------------------------------------------//
  1667. CPropVariant& CPropVariant::operator=( const CAH& src )
  1668. {
  1669.     Clear() ;
  1670.     PropVectorAssignShallow( cah, vt, src, VT_I8 ) ; 
  1671.     return *this ;
  1672. }
  1673. //-------------------------------------------------------------------------//
  1674. CPropVariant& CPropVariant::operator=( const CAUH& src )
  1675. {
  1676.     Clear() ;
  1677.     PropVectorAssignShallow( cauh, vt, src, VT_UI8 ) ; 
  1678.     return *this ;
  1679. }
  1680. //-------------------------------------------------------------------------//
  1681. CPropVariant& CPropVariant::operator=( const CADBL& src )
  1682. {
  1683.     Clear() ;
  1684.     PropVectorAssignShallow( cadbl, vt, src, VT_R8 ) ; 
  1685.     return *this ;
  1686. }
  1687. //-------------------------------------------------------------------------//
  1688. CPropVariant& CPropVariant::operator=( const CACY& src )
  1689. {
  1690.     Clear() ;
  1691.     PropVectorAssignShallow( cacy, vt, src, VT_CY ) ; 
  1692.     return *this ;
  1693. }
  1694. //-------------------------------------------------------------------------//
  1695. CPropVariant& CPropVariant::operator=( const CADATE& src )
  1696. {
  1697.     Clear() ;
  1698.     PropVectorAssignShallow( cadate, vt, src, VT_DATE ) ; 
  1699.     return *this ;
  1700. }
  1701. //-------------------------------------------------------------------------//
  1702. CPropVariant& CPropVariant::operator=( const CAFILETIME& src )
  1703. {
  1704.     Clear() ;
  1705.     PropVectorAssignShallow( cafiletime, vt, src, VT_FILETIME ) ; 
  1706.     return *this ;
  1707. }
  1708. //-------------------------------------------------------------------------//
  1709. CPropVariant& CPropVariant::operator=( const CACLSID& src )
  1710. {
  1711.     Clear() ;
  1712.     PropVectorAssignShallow( cauuid, vt, src, VT_CLSID ) ; 
  1713.     return *this ;
  1714. }
  1715. //-------------------------------------------------------------------------//
  1716. CPropVariant& CPropVariant::operator=( const CACLIPDATA& src )
  1717. {
  1718.     Clear() ;
  1719.     if( PropVectorAssignShallow( caclipdata, vt, src, VT_CF ) )
  1720.     {
  1721.         for( ULONG i=0, cb; i<src.cElems; i++ )
  1722.         {
  1723.             caclipdata.pElems[i].cbSize     = 0 ;
  1724.             caclipdata.pElems[i].pClipData  = NULL ;
  1725.             
  1726.             if( (cb = CBPCLIPDATA( src.pElems[i] ))!=0 &&
  1727.                 src.pElems[i].pClipData!=NULL )
  1728.             {
  1729.                 if( (caclipdata.pElems[i].pClipData = 
  1730.                         (BYTE*)AllocAndCopy( src.pElems[i].pClipData, cb ))!=NULL )
  1731.                     caclipdata.pElems[i].cbSize = src.pElems[i].cbSize ;
  1732.             }
  1733.         }
  1734.     }
  1735.     return *this ;
  1736. }
  1737. //-------------------------------------------------------------------------//
  1738. CPropVariant& CPropVariant::operator=( const CABSTR& src )
  1739. {
  1740.     Clear() ;
  1741.     //  Do shallow copy    
  1742.     if( PropVectorAssignShallow( cabstr, vt, src, VT_BSTR ) )
  1743.     {
  1744.         //  Do deep copy
  1745.         for( ULONG i=0; i<src.cElems; i++ )
  1746.         {
  1747.             cabstr.pElems[i] = src.pElems[i]==NULL ? 
  1748.                 NULL : SysAllocString( src.pElems[i] ) ;
  1749.         }
  1750.     }
  1751.     return *this ;
  1752. }
  1753. //-------------------------------------------------------------------------//
  1754. CPropVariant& CPropVariant::operator=( const CALPSTR& src )
  1755. {
  1756.     Clear() ;
  1757.     //  Do shallow copy
  1758.     if( PropVectorAssignShallow( calpstr, vt, src, VT_LPSTR ) )
  1759.     {
  1760.         //  Do deep copy
  1761.         for( ULONG i=0; i<src.cElems; i++ )
  1762.         {
  1763.             if( src.pElems[i]!=NULL )
  1764.             {
  1765.                 UINT cch = lstrlenA( src.pElems[i] )+1 ;
  1766.                 calpstr.pElems[i] = (LPSTR)AllocAndCopy( src.pElems[i], cch ) ;
  1767.             }
  1768.         }
  1769.     }
  1770.     return *this ;
  1771. }
  1772. //-------------------------------------------------------------------------//
  1773. CPropVariant& CPropVariant::operator=( const CALPWSTR& src )
  1774. {
  1775.     Clear() ;
  1776.     //  Do shallow copy
  1777.     if( PropVectorAssignShallow( calpwstr, vt, src, VT_LPWSTR ) )
  1778.     {
  1779.         //  Do deep copy
  1780.         for( ULONG i=0; i<src.cElems; i++ )
  1781.         {
  1782.             if( src.pElems[i]!=NULL )
  1783.             {
  1784.                 UINT cch = lstrlenW( src.pElems[i] )+1 ;
  1785.                 calpwstr.pElems[i] = (LPWSTR)AllocAndCopy( src.pElems[i], cch ) ;
  1786.             }
  1787.         }
  1788.     }
  1789.     return *this ;
  1790. }
  1791. //-------------------------------------------------------------------------//
  1792. CPropVariant& CPropVariant::operator=( const CAPROPVARIANT& src )
  1793. {
  1794.     Clear() ;
  1795.     if( PropVectorAssignShallow( capropvar, vt, src, VT_VARIANT ) )
  1796.     {
  1797.         for( ULONG i=0; i<src.cElems; i++ )
  1798.             ::PropVariantCopy( &capropvar.pElems[i], &src.pElems[i] ) ;    
  1799.     }
  1800.     return *this ;
  1801. }
  1802. //-------------------------------------------------------------------------//
  1803. int CPropVariant::CompareText( 
  1804.     const CPropVariant& varOther, 
  1805.     ULONG uFlags,
  1806.     IN OPTIONAL LPCTSTR pszFmt, 
  1807.     IN OPTIONAL ULONG dwFlags ) const
  1808. {
  1809.     BSTR    bstrThis  = NULL, 
  1810.             bstrOther = NULL;
  1811.     HRESULT hrThis, 
  1812.             hrOther ;
  1813.     int     iRet = 0 ;
  1814.     hrThis  = GetDisplayText( bstrThis, pszFmt, dwFlags ) ;
  1815.     hrOther = varOther.GetDisplayText( bstrOther, pszFmt, dwFlags ) ;
  1816.     if( SUCCEEDED( hrThis ) && SUCCEEDED( hrOther ) )
  1817.         iRet = uFlags & PVCF_IGNORECASE ? lstrcmpiW( bstrThis, bstrOther ) :
  1818.                                           lstrcmpW( bstrThis, bstrOther ) ;
  1819.     else if( SUCCEEDED( hrThis ) )
  1820.         iRet = 1 ;
  1821.     else if( SUCCEEDED( hrOther ) )
  1822.         iRet = -1 ;
  1823.     SysFreeString( bstrThis ) ;
  1824.     SysFreeString( bstrOther ) ;
  1825.     
  1826.     return iRet ;
  1827. }
  1828. //-------------------------------------------------------------------------//
  1829. //  Write to registry
  1830. HRESULT CPropVariant::WriteValue( HKEY hKey, LPCTSTR pszValueName ) const
  1831. {
  1832.     return PropVariantWriteRegistry( hKey, pszValueName, *this ) ;
  1833. }
  1834. //-------------------------------------------------------------------------//
  1835. //  Read from registry
  1836. HRESULT CPropVariant::ReadValue( HKEY hKey, LPCTSTR pszValueName )
  1837. {
  1838.     Clear() ;
  1839.     return PropVariantReadRegistry( hKey, pszValueName, *this ) ;
  1840. }                           
  1841. //-------------------------------------------------------------------------//
  1842. //  class CDisplayPropVariant : public CPropVariant 
  1843. //-------------------------------------------------------------------------//
  1844. //-------------------------------------------------------------------------//
  1845. //  Generates display text for the object, optionally using the provided
  1846. //  formatting string
  1847. HRESULT CDisplayPropVariant::CreateDisplayText( 
  1848.     IN OPTIONAL LPCTSTR pszFmt,
  1849.     IN OPTIONAL ULONG dwFlags )
  1850. {
  1851.     BSTR    bstrDisplay = NULL ;
  1852.     HRESULT hr = GetDisplayText( bstrDisplay, pszFmt, dwFlags ) ;
  1853.     if( SUCCEEDED( hr ) )
  1854.         SetDisplayText( bstrDisplay ) ;
  1855.     return hr ;
  1856. }
  1857. //-------------------------------------------------------------------------//
  1858. void CDisplayPropVariant::SetDisplayTextT( IN LPCTSTR pszDisplay )
  1859. {
  1860.     BSTR bstrDisplay = NULL ;
  1861.     if( pszDisplay )
  1862.     {
  1863.         USES_CONVERSION ;
  1864.         bstrDisplay = SysAllocString( T2W( (LPTSTR)pszDisplay ) ) ;
  1865.     }
  1866.     SetDisplayText( bstrDisplay ) ;
  1867. }
  1868. //-------------------------------------------------------------------------//
  1869. //  Assigns display text.
  1870. void CDisplayPropVariant::SetDisplayText( BSTR bstrDisplay )
  1871. {
  1872.     if( m_bstrDisplay )
  1873.     {
  1874.         SysFreeString( m_bstrDisplay ) ;
  1875.         m_bstrDisplay = NULL ;
  1876.     }
  1877.     m_bstrDisplay = SysAllocString( bstrDisplay ) ;
  1878. }
  1879. //-------------------------------------------------------------------------//
  1880. //  class CPropertyUID : public tagPUID
  1881. //-------------------------------------------------------------------------//
  1882. //-------------------------------------------------------------------------//
  1883. //  hashing method for class CPropertyUID
  1884. ULONG CPropertyUID::Hash() const 
  1885.     int   cb = sizeof(fmtid) ; 
  1886.     ULONG nHash = 0 ;
  1887.     BYTE* p = (BYTE*)&fmtid ;
  1888.     while( cb-- )
  1889.         nHash += *p++ ;
  1890.     nHash += propid ;
  1891.     return  nHash ;
  1892. }