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

Windows Kernel

Development Platform:

Visual C++

  1. #include "precomp.h"
  2. HRESULT GetMediaManagerThumbnail( IPropertyStorage * pPropStg,
  3.                                   const SIZE * prgSize,
  4.                                   DWORD dwClrDepth,
  5.                                   HPALETTE hpal,
  6.                                   BOOL fOrigSize,
  7.                                   HBITMAP * phBmpThumbnail );
  8.                                   
  9. HRESULT GetDocFileThumbnail( IPropertyStorage * pPropStg,
  10.                              const SIZE * prgSize,
  11.                              DWORD dwClrDepth,
  12.                              HPALETTE hpal,
  13.                              BOOL fOrigSize,
  14.                              HBITMAP * phBmpThumbnail );
  15. // PACKEDMETA struct for DocFile thumbnails.
  16. typedef struct
  17. {
  18.     WORD    mm;
  19.     WORD    xExt;
  20.     WORD    yExt;
  21.     WORD    dummy;
  22. } PACKEDMETA;
  23. VOID CalcMetaFileSize( HDC hDC, PACKEDMETA * pMeta, const SIZEL * prgSize, RECT * pRect);
  24. WCHAR const c_szMIC[] = L".MIC";
  25. WCHAR c_szThumbnailProp[] = L"Thumbnail";
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. CDocFileHandler::CDocFileHandler()
  28. {
  29.     m_pszPath = NULL;
  30. }
  31. ///////////////////////////////////////////////////////////////////////////////////////////////////
  32. CDocFileHandler::~CDocFileHandler()
  33. {
  34.     if ( m_pszPath )
  35.     {
  36.         LocalFree( m_pszPath );
  37.     }
  38. }
  39. ///////////////////////////////////////////////////////////////////////////////////////////////////
  40. STDMETHODIMP CDocFileHandler::GetLocation ( LPWSTR szFileName,
  41.                                             DWORD cchMax,
  42.                                             DWORD * pdwPriority,
  43.                                             const SIZE * prgSize,
  44.                                             DWORD dwRecClrDepth,
  45.                                             DWORD *pdwFlags )
  46. {
  47.     if ( !szFileName || !pdwFlags || ((*pdwFlags & IEIFLAG_ASYNC) && !pdwPriority ) || !prgSize )
  48.     {
  49.         return E_INVALIDARG;
  50.     }
  51.     if ( !m_pszPath )
  52.     {
  53.         return E_UNEXPECTED;
  54.     }
  55.     m_rgSize = *prgSize;
  56.     m_dwRecClrDepth = dwRecClrDepth;
  57.     
  58.     // just copy the current path into the buffer as we do not share thumbnails...
  59.     StrCpyNW( szFileName, m_pszPath, cchMax );
  60.     HRESULT hr = NOERROR;
  61.     if ( *pdwFlags & IEIFLAG_ASYNC )
  62.     {
  63.         // we support async 
  64.         hr = E_PENDING;
  65.         *pdwPriority = PRIORITY_NORMAL;
  66.     }
  67.     m_fOrigSize = BOOLIFY(*pdwFlags & IEIFLAG_ORIGSIZE );
  68.     
  69.     // we don't want it cached....
  70.     *pdwFlags &= ~IEIFLAG_CACHE;
  71.     return hr;
  72. }
  73. ///////////////////////////////////////////////////////////////////////////////////////////////////
  74. STDMETHODIMP CDocFileHandler::Extract ( HBITMAP * phBmpThumbnail)
  75. {
  76.     if ( !m_pszPath )
  77.     {
  78.         return E_UNEXPECTED;
  79.     }
  80.     
  81.     if ( !phBmpThumbnail )
  82.     {
  83.         return E_INVALIDARG;
  84.     }
  85.     // find the extension.....
  86.     LPWSTR pszExt = StrRChrW( m_pszPath, NULL, WCHAR('.'));
  87.     if ( !pszExt )
  88.     {
  89.         return E_UNEXPECTED;
  90.     }
  91.     
  92.     LPSTORAGE pStorage = NULL;
  93.     HRESULT hr = StgOpenStorage( m_pszPath,
  94.                                  NULL,
  95.                                  STGM_READ | STGM_SHARE_EXCLUSIVE,
  96.                                  NULL,
  97.                                  NULL,
  98.                                  & pStorage );
  99.     if ( FAILED( hr ))
  100.     {
  101.         return hr;
  102.     }
  103.     LPPROPERTYSETSTORAGE pPropSetStg = NULL;
  104.     hr = pStorage->QueryInterface( IID_IPropertySetStorage, (LPVOID *) &pPropSetStg );
  105.     if ( FAILED( hr ))
  106.     {
  107.         pStorage->Release();
  108.         return hr;
  109.     }
  110.     
  111.     FMTID fmtidPropSet = FMTID_SummaryInformation;
  112.     BOOL fMediaManager = FALSE;
  113.     // "MIC" Microsoft Image Composer files needs special casing because they use
  114.     // the Media Manager internal thumbnail propertyset ... (by what it would be like
  115.     // to be standard for once ....)
  116.     if ( StrCmpIW( pszExt, c_szMIC ) == 0 )
  117.     {
  118.         // switch to the Media Manager thumbnail propertyset....
  119.         fmtidPropSet = FMTID_CmsThumbnailPropertySet;
  120.         fMediaManager = TRUE;
  121.     }
  122.     
  123.     LPPROPERTYSTORAGE pPropSet;
  124.     hr = pPropSetStg->Open( fmtidPropSet,
  125.                             STGM_READ | STGM_SHARE_EXCLUSIVE,
  126.                             &pPropSet );
  127.     if ( FAILED( hr ))
  128.     {
  129.         pStorage->Release();
  130.         pPropSetStg->Release();
  131.         return hr;
  132.     }
  133.     HPALETTE hpal = NULL;
  134.     if ( m_dwRecClrDepth == 8 )
  135.     {
  136.         hpal = SHCreateShellPalette( NULL );
  137.     }
  138.     else if ( m_dwRecClrDepth < 8 )
  139.     {
  140.         hpal = (HPALETTE) GetStockObject( DEFAULT_PALETTE );
  141.     }
  142.     
  143.     if ( fMediaManager )
  144.     {
  145.         hr = GetMediaManagerThumbnail( pPropSet, &m_rgSize, m_dwRecClrDepth, hpal, m_fOrigSize, phBmpThumbnail );
  146.     }
  147.     else
  148.     {
  149.         hr = GetDocFileThumbnail( pPropSet, &m_rgSize, m_dwRecClrDepth, hpal, m_fOrigSize, phBmpThumbnail );
  150.     }
  151.     if ( hpal )
  152.     {
  153.         DeletePalette( hpal );
  154.     }
  155.     
  156.     pPropSet->Release();
  157.     pPropSetStg->Release();
  158.     pStorage->Release();
  159.     
  160.     return hr;   
  161. }
  162. ///////////////////////////////////////////////////////////////////////////////////////////////////
  163. STDMETHODIMP CDocFileHandler::GetDateStamp ( FILETIME * pftDateStamp )
  164. {
  165.     Assert( pftDateStamp );
  166.     
  167.     HANDLE hFind;
  168.     WIN32_FIND_DATAW rgData;
  169.     
  170.     hFind = FindFirstFileWrapW( m_pszPath, &rgData );
  171.     if ( INVALID_HANDLE_VALUE != hFind )
  172.     {
  173.         *pftDateStamp = rgData.ftLastWriteTime;
  174.         FindClose( hFind );
  175.         return S_OK;
  176.     }
  177.     return E_FAIL;
  178. }
  179. ///////////////////////////////////////////////////////////////////////////////////////////////////
  180. STDMETHODIMP CDocFileHandler::Load(LPCOLESTR pszFileName, DWORD dwMode)
  181. {
  182.     // ignore the DWORD dwMode, as we only ever open in read mode....
  183.     if ( !pszFileName )
  184.     {
  185.         return E_INVALIDARG;
  186.     }
  187.     
  188.     DWORD dwAttrs = GetFileAttributesWrapW( pszFileName );
  189.     if (( dwAttrs != (DWORD) -1) && (dwAttrs & FILE_ATTRIBUTE_OFFLINE ))
  190.     {
  191.         return E_FAIL;
  192.     }
  193.     if ( m_pszPath )
  194.     {
  195.         LocalFree( m_pszPath );
  196.     }
  197.     UINT cLen = lstrlenW( pszFileName ) + 1;
  198.     m_pszPath = (LPWSTR) LocalAlloc( LPTR, cLen * sizeof(WCHAR));
  199.     if ( !m_pszPath )
  200.     {
  201.         return E_OUTOFMEMORY;
  202.     }
  203.     StrCpyW( m_pszPath, pszFileName );
  204.     return NOERROR;
  205. }
  206. /////////////////////////////////////////////////////////////////////////////////////////
  207. HRESULT GetMediaManagerThumbnail( IPropertyStorage * pPropStg,
  208.                                   const SIZE * prgSize,
  209.                                   DWORD dwClrDepth,
  210.                                   HPALETTE hpal,
  211.                                   BOOL fOrigSize,
  212.                                   HBITMAP * phBmpThumbnail )
  213. {
  214.     // current version of media manager simply stores the DIB data in a under a 
  215.     // named property Thumbnail...
  216.     PROPSPEC propSpec;
  217.     PROPVARIANT pvarResult;
  218.     ZeroMemory( &pvarResult, sizeof( pvarResult ));
  219.     
  220.     if ( !pPropStg || !prgSize )
  221.     {
  222.         return E_INVALIDARG;
  223.     }
  224.     
  225.     // read the thumbnail property from the property storage.
  226.     propSpec.ulKind = PRSPEC_LPWSTR;
  227.     propSpec.lpwstr = c_szThumbnailProp;
  228.     
  229.     HRESULT hr = pPropStg->ReadMultiple( 1, &propSpec, &pvarResult );
  230.     if( SUCCEEDED( hr ) )
  231.     {
  232.         BITMAPINFO * pbi;
  233.         LPVOID pBits;
  234.         pbi = ( BITMAPINFO * )pvarResult.blob.pBlobData;
  235.         pBits = CalcBitsOffsetInDIB( pbi );
  236.         
  237.         hr = E_FAIL;
  238.         if ( pbi->bmiHeader.biSize == sizeof( BITMAPINFOHEADER ) )
  239.         {
  240.             if ( ConvertDIBSECTIONToThumbnail( pbi, pBits, phBmpThumbnail, prgSize, dwClrDepth, hpal, 15, fOrigSize ))
  241.             {
  242.                 hr = NOERROR;
  243.             }
  244.         }
  245.         PropVariantClear( &pvarResult );
  246.     }
  247.     
  248.     return hr;
  249. }
  250. /////////////////////////////////////////////////////////////////////////////////////////
  251. HRESULT GetDocFileThumbnail( IPropertyStorage * pPropStg,
  252.                              const SIZE * prgSize,
  253.                              DWORD dwClrDepth,
  254.                              HPALETTE hpal,
  255.                              BOOL fOrigSize,
  256.                              HBITMAP * phBmpThumbnail )
  257. {
  258.     PROPSPEC propSpec;
  259.     PROPVARIANT pvarResult;
  260.     HDC hDC = GetDC( GetDesktopWindow( ) );
  261.     HBITMAP hBmp = NULL;
  262.     HRESULT hr = S_OK;
  263.     if ( !pPropStg || !prgSize )
  264.     {
  265.         return E_INVALIDARG;
  266.     }
  267.     
  268.     HDC hMemDC = CreateCompatibleDC( hDC );
  269.     if ( hMemDC == NULL )
  270.     {
  271.         return E_OUTOFMEMORY;
  272.     }
  273.     // read the thumbnail property from the property storage.
  274.     propSpec.ulKind = PRSPEC_PROPID;
  275.     propSpec.propid = PIDSI_THUMBNAIL;
  276.     hr = pPropStg->ReadMultiple( 1, &propSpec, &pvarResult );
  277.     if( SUCCEEDED( hr ) )
  278.     {
  279.         // make sure we are dealing with a clipboard format. CLIPDATA
  280.         if ( ( pvarResult.vt == VT_CF ) && ( pvarResult.pclipdata->ulClipFmt == -1 ) )
  281.         {
  282.             LPDWORD pdwCF = ( LPDWORD )pvarResult.pclipdata->pClipData;
  283.             LPBYTE  pStruct = pvarResult.pclipdata->pClipData + sizeof( DWORD );
  284.             if ( *pdwCF == CF_METAFILEPICT )
  285.             {
  286.                 SetMapMode( hMemDC, MM_TEXT );
  287.                 
  288.                 // handle thumbnail that is a metafile.
  289.                 PACKEDMETA * pMeta = ( PACKEDMETA * )pStruct;
  290.                 LPBYTE pData = pStruct + sizeof( PACKEDMETA );
  291.                 HMETAFILE hMF;
  292.                 RECT rect;
  293.                 UINT cbSize = pvarResult.pclipdata->cbSize - sizeof( DWORD ) - sizeof( pMeta->mm ) - 
  294.                 sizeof( pMeta->xExt ) - sizeof( pMeta->yExt ) - sizeof( pMeta->dummy );
  295.                 // save as a metafile.
  296.                 hMF = SetMetaFileBitsEx( cbSize, pData );
  297.                 if ( hMF )
  298.                 {    
  299.                     SIZE rgNewSize;
  300.                     
  301.                     // use the mapping mode to calc the current size
  302.                     CalcMetaFileSize( hMemDC, pMeta, prgSize, & rect );
  303.                     
  304.                     CalculateAspectRatio( prgSize, &rect );
  305.                     if ( fOrigSize )
  306.                     {
  307.                         // use the aspect rect to refigure the size...
  308.                         rgNewSize.cx = rect.right - rect.left;
  309.                         rgNewSize.cy = rect.bottom - rect.top;
  310.                         prgSize = &rgNewSize;
  311.                         
  312.                         // adjust the rect to be the same as the size (which is the size of the metafile)
  313.                         rect.right -= rect.left;
  314.                         rect.bottom -= rect.top;
  315.                         rect.left = 0;
  316.                         rect.top = 0;
  317.                     }
  318.                     if ( CreateSizedDIBSECTION( prgSize, dwClrDepth, hpal, NULL, &hBmp, NULL, NULL ))
  319.                     {
  320.                         HGDIOBJ hOldBmp = SelectObject( hMemDC, hBmp );
  321.                         HGDIOBJ hBrush = GetStockObject( THUMBNAIL_BACKGROUND_BRUSH );
  322.                         HGDIOBJ hOldBrush = SelectObject( hMemDC, hBrush );
  323.                         HGDIOBJ hPen = GetStockObject( THUMBNAIL_BACKGROUND_PEN );
  324.                         HGDIOBJ hOldPen = SelectObject( hMemDC, hPen );
  325.                         Rectangle( hMemDC, 0, 0, prgSize->cx, prgSize->cy );
  326.         
  327.                         SelectObject( hMemDC, hOldBrush );
  328.                         SelectObject( hMemDC, hOldPen );
  329.                     
  330.                         int iXBorder = 0;
  331.                         int iYBorder = 0;
  332.                         if ( rect.left == 0 )
  333.                         {
  334.                             iXBorder ++;
  335.                         }
  336.                         if ( rect.top == 0 )
  337.                         {
  338.                             iYBorder ++;
  339.                         }
  340.                         
  341.                         SetViewportExtEx( hMemDC, rect.right - rect.left - 2 * iXBorder, rect.bottom - rect.top - 2 * iYBorder, NULL );
  342.                         SetViewportOrgEx( hMemDC, rect.left + iXBorder, rect.top + iYBorder, NULL );
  343.                         SetMapMode( hMemDC, pMeta->mm );
  344.                         // play the metafile.
  345.                         BOOL bRet = PlayMetaFile( hMemDC, hMF );
  346.                         if ( bRet )
  347.                         {
  348.                             *phBmpThumbnail = hBmp ;
  349.                             if ( *phBmpThumbnail == NULL )
  350.                             {
  351.                                 // unable to get thumbnail bitmap.
  352.                                 hr = E_FAIL;
  353.                             }
  354.                         }
  355.                         DeleteMetaFile( hMF );
  356.                         SelectObject( hMemDC, hOldBmp );
  357.                         if ( FAILED( hr ) && hBmp )
  358.                         {
  359.                             DeleteObject( hBmp );
  360.                         }
  361.                     }
  362.                     else
  363.                     {
  364.                         hr = DV_E_CLIPFORMAT;
  365.                     }
  366.                 }
  367.             }
  368.             else if ( *pdwCF == CF_DIB )
  369.             {
  370.                 // handle thumbnail that is a metafile.
  371.                 BITMAPINFO * pDib = (BITMAPINFO *) pStruct;
  372.                 if ( pDib->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
  373.                 {
  374.                     LPVOID pBits = CalcBitsOffsetInDIB( pDib );
  375.                     
  376.                     if ( ConvertDIBSECTIONToThumbnail( pDib, pBits, phBmpThumbnail, prgSize, dwClrDepth, hpal, 15, fOrigSize ) == FALSE )
  377.                     {
  378.                         hr = DV_E_CLIPFORMAT;
  379.                     }
  380.                 }
  381.             }
  382.             else
  383.             {
  384.                 hr = DV_E_CLIPFORMAT;
  385.             }
  386.         }
  387.         else
  388.         {
  389.             hr = DV_E_CLIPFORMAT;
  390.         }
  391.         PropVariantClear( &pvarResult );
  392.     }
  393.     DeleteDC( hMemDC );
  394.     ReleaseDC( GetDesktopWindow( ), hDC );
  395.     return hr;
  396. }
  397. ///////////////////////////////////////////////////////////////////////////////////////////////////
  398. VOID CalcMetaFileSize( HDC hDC, PACKEDMETA * prgMeta, const SIZEL * prgSize, RECT * prgRect)
  399. {
  400.     Assert( prgMeta && prgRect );
  401.     prgRect->left = 0;
  402.     prgRect->top = 0;
  403.     if ( !prgMeta->xExt || !prgMeta->yExt )
  404.     {
  405.         // no size, then just use the size rect ...
  406.         prgRect->right = prgSize->cx;
  407.         prgRect->bottom = prgSize->cy;
  408.     }
  409.     else
  410.     {
  411.         // set the mapping mode....
  412.         SetMapMode( hDC, prgMeta->mm );
  413.         if ( prgMeta->mm == MM_ISOTROPIC || prgMeta->mm == MM_ANISOTROPIC )
  414.         {
  415.             // we must set the ViewPortExtent and the window extent to get the scaling
  416.             SetWindowExtEx( hDC, prgMeta->xExt, prgMeta->yExt, NULL );
  417.             SetViewportExtEx( hDC, prgMeta->xExt, prgMeta->yExt, NULL );
  418.         }
  419.         POINT pt;
  420.         pt.x = prgMeta->xExt;
  421.         pt.y = prgMeta->yExt;
  422.         // convert to pixels....
  423.         LPtoDP( hDC, &pt, 1);
  424.         prgRect->right = abs( pt.x );
  425.         prgRect->bottom = abs( pt.y );
  426.     }
  427. }
  428. ///////////////////////////////////////////////////////////////////////////////////////////////////
  429. STDMETHODIMP CDocFileHandler::GetClassID(CLSID * pCLSID )
  430. {
  431.     return E_NOTIMPL;
  432. }
  433. ///////////////////////////////////////////////////////////////////////////////////////////////////
  434. STDMETHODIMP CDocFileHandler::IsDirty( )
  435. {
  436.     return S_FALSE;
  437. }
  438. ///////////////////////////////////////////////////////////////////////////////////////////////////
  439. STDMETHODIMP CDocFileHandler::Save(LPCOLESTR pszFileName, BOOL fRemember)
  440. {
  441.     return E_NOTIMPL;
  442. }
  443. ///////////////////////////////////////////////////////////////////////////////////////////////////
  444. STDMETHODIMP CDocFileHandler::SaveCompleted(LPCOLESTR pszFileName)
  445. {
  446.     return E_NOTIMPL;
  447. }
  448. ///////////////////////////////////////////////////////////////////////////////////////////////////
  449. STDMETHODIMP CDocFileHandler::GetCurFile(LPOLESTR * ppszFileName)
  450. {
  451.     return E_NOTIMPL;
  452. }