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

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. //#include "local.h"
  3. #include "sccls.h"
  4. #include "htmlbm.h"
  5. //#include "deskstat.h"
  6. //#include "dutil.h"
  7. #include "isfband.h"
  8. #include "runtask.h"
  9. #include "dbgmem.h"
  10. #ifndef POSTPOSTSPLIT
  11. static const GUID TOID_Thumbnail = { 0xadec3450, 0xe907, 0x11d0, {0xa5, 0x7b, 0x00, 0xc0, 0x4f, 0xc2, 0xf7, 0x6a} };
  12. HRESULT CDiskCacheTask_Create( CLogoBase * pView,
  13.                                LPSHELLIMAGESTORE pImageStore,
  14.                                LPCWSTR pszItem,
  15.                                LPCWSTR pszGLocation,
  16.                                DWORD dwItem,
  17.                                LPRUNNABLETASK * ppTask );
  18.                                
  19. class CDiskCacheTask : public CRunnableTask
  20. {
  21.     public:
  22.         CDiskCacheTask();
  23.         ~CDiskCacheTask();
  24.         STDMETHODIMP RunInitRT( void );
  25.         friend HRESULT CDiskCacheTask_Create( CLogoBase * pView,
  26.                                LPSHELLIMAGESTORE pImageStore,
  27.                                LPCWSTR pszItem,
  28.                                LPCWSTR pszGLocation,
  29.                                DWORD dwItem,
  30.                                const SIZE * prgSize,
  31.                                LPRUNNABLETASK * ppTask );
  32.     protected:
  33.         HRESULT PrepImage( HBITMAP * phBmp );
  34.         
  35.         LPSHELLIMAGESTORE _pImageStore;
  36.         WCHAR _szItem[MAX_PATH];
  37.         WCHAR _szGLocation[MAX_PATH];
  38.         CLogoBase * _pView;
  39.         DWORD _dwItem;
  40.         SIZE m_rgSize;
  41. };
  42. // CreateInstance
  43. HRESULT CThumbnail_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  44. {
  45.     *ppunk = NULL;
  46.     CThumbnail *thumbnailInstance = new CThumbnail();
  47.     if (thumbnailInstance != NULL)
  48.     {
  49.         *ppunk = SAFECAST(thumbnailInstance, IThumbnail*);
  50.         return S_OK;
  51.     }
  52.     return E_OUTOFMEMORY;
  53. }
  54. // Constructor / Destructor
  55. CThumbnail::CThumbnail(void):
  56.     m_cRef(1)
  57. {
  58.     DllAddRef();
  59. }
  60. CThumbnail::~CThumbnail(void)
  61. {
  62.     if (_pTaskScheduler)
  63.     {
  64.         _pTaskScheduler->RemoveTasks(TOID_Thumbnail, ITSAT_DEFAULT_LPARAM, FALSE);
  65.         _pTaskScheduler->Release();
  66.         _pTaskScheduler = NULL;
  67.     }
  68.     DllRelease();
  69. }
  70. // *** IUnknown ***
  71. HRESULT CThumbnail::QueryInterface(REFIID riid, void **ppvObj)
  72. {
  73.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IThumbnail))
  74.     {
  75.         *ppvObj = SAFECAST(this, IThumbnail*);
  76.     }
  77.     else
  78.     {
  79.         *ppvObj = NULL;
  80.         return E_NOINTERFACE;
  81.     }
  82.     AddRef();
  83.     return S_OK;
  84. }
  85. ULONG CThumbnail::AddRef(void)
  86. {
  87.     m_cRef++;
  88.     return m_cRef;
  89. }
  90. ULONG CThumbnail::Release(void)
  91. {
  92.     ASSERT(m_cRef > 0);
  93.     m_cRef--;
  94.     if (m_cRef > 0)
  95.     {
  96.         return m_cRef;
  97.     }
  98.     delete this;
  99.     return 0;
  100. }
  101. // *** IThumbnail ***
  102. HRESULT CThumbnail::Init(HWND hwnd, UINT uMsg)
  103. {
  104.     _hwnd = hwnd;
  105.     _uMsg = uMsg;
  106.     _pTaskScheduler = NULL;
  107.     return S_OK;
  108. }   // Init
  109. HRESULT CThumbnail::GetBitmap(LPCWSTR wszFile, DWORD dwItem, LONG lWidth, LONG lHeight)
  110. {
  111.     HRESULT hr = E_FAIL;
  112.     //
  113.     // Make sure we have a task scheduler.
  114.     //
  115.     if (!_pTaskScheduler)
  116.     {
  117.         if (SUCCEEDED(CoCreateInstance(CLSID_ShellTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_IShellTaskScheduler, (void **)&_pTaskScheduler)))
  118.         {
  119.             // make sure RemoveTasks() actually kills old tasks even if they're not done yet
  120.             _pTaskScheduler->Status(ITSSFLAG_KILL_ON_DESTROY, ITSS_THREAD_TIMEOUT_NO_CHANGE);
  121.         }
  122.     }
  123.     if (_pTaskScheduler)
  124.     {
  125.         //
  126.         // Kill any old tasks in the scheduler.
  127.         //
  128.         _pTaskScheduler->RemoveTasks(TOID_Thumbnail, ITSAT_DEFAULT_LPARAM, FALSE);
  129.         if (wszFile)
  130.         {
  131.             LPITEMIDLIST pidl = ILCreateFromPathW(wszFile);
  132.             if (pidl)
  133.             {
  134.                 LPCITEMIDLIST pidlFile;
  135.                 IShellFolder *psf;
  136.                 if (SUCCEEDED(SHBindToIDListParent(pidl, IID_IShellFolder, (void **)&psf, &pidlFile)))
  137.                 {
  138.                     IExtractImage *pei;
  139.                     if (SUCCEEDED(psf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&pidlFile, IID_IExtractImage, NULL, (void **)&pei)))
  140.                     {
  141.                         DWORD dwPriority;
  142.                         DWORD dwFlags = IEIFLAG_ASYNC | IEIFLAG_ASPECT | IEIFLAG_OFFLINE;
  143.                         SIZEL rgSize;
  144.                         rgSize.cx = lWidth;
  145.                         rgSize.cy = lHeight;
  146.                         WCHAR szBufferW[MAX_PATH];
  147.                         HRESULT hr2 = pei->GetLocation(szBufferW, ARRAYSIZE(szBufferW), &dwPriority, &rgSize, SHGetCurColorRes(), &dwFlags);
  148.                         if ( hr2 == E_PENDING)
  149.                         {
  150.                             // now get the date stamp and check the disk cache....
  151.                             FILETIME ftImageTimeStamp;
  152.                             BOOL fNoDateStamp = TRUE;
  153.                             LPEXTRACTIMAGE2 pei2;
  154.                             // try it in the background...
  155.                             LPRUNNABLETASK prt;
  156.                             // od they support date stamps....
  157.                             if ( SUCCEEDED( pei->QueryInterface( IID_IExtractImage2, (void **) &pei2)))
  158.                             {
  159.                                 if ( SUCCEEDED( pei2->GetDateStamp( & ftImageTimeStamp )))
  160.                                 {
  161.                                     // Houston, we have a date stamp..
  162.                                     fNoDateStamp = FALSE;
  163.                                 }
  164.         
  165.                                 pei2->Release();
  166.                             }
  167.                             // if it is in the cache, and it is an uptodate image, then fetch from disk....
  168.                             // if the timestamps are wrong, then the extract code further down will then try
  169.                             // we only test the cache on NT5 because the templates are old on other platforms and 
  170.                             // thus the image will be the wrong size...
  171.                             if ( IsOS( OS_NT5 ) && IsItInCache( wszFile, szBufferW, ( fNoDateStamp ? NULL : &ftImageTimeStamp )))
  172.                             {
  173.                                 hr = CDiskCacheTask_Create( this, _pImageStore, wszFile, szBufferW,  
  174.                                                             dwItem, &rgSize, & prt );
  175.                                 if ( SUCCEEDED( hr ))
  176.                                 {
  177.                                     // let go of the image store, so the task has the only ref and the lock..
  178.                                     ATOMICRELEASE( _pImageStore );
  179.                                 }
  180.                             }
  181.                             else
  182.                             {
  183.                                 // Cannot hold the prt which is returned in a member variable since that
  184.                                 // would be a circular reference
  185.                                 hr = CExtractImageTask_Create(this, 
  186.                                                 pei, L"", dwItem,
  187.                                                 -1, EITF_SAVEBITMAP | EITF_ALWAYSCALL, &prt);
  188.                             }
  189.                             
  190.                             //
  191.                             // Create our own task to perform the extraction.
  192.                             //
  193.                             if ( SUCCEEDED( hr ))
  194.                             {
  195.                                 //
  196.                                 // Add the task to the scheduler.
  197.                                 //
  198.                                 if (SUCCEEDED(_pTaskScheduler->AddTask(prt, TOID_Thumbnail, ITSAT_DEFAULT_LPARAM, dwPriority)))
  199.                                 {
  200.                                     // now belongs to the scheduler thread
  201.                                     remove_from_memlist( prt );
  202.                                     hr = S_OK;
  203.                                 }
  204.                                 else
  205.                                 {
  206.                                     TraceMsg(TF_WARNING, "hb: Could not add task!");
  207.                                 }
  208.                                 prt->Release();
  209.                             }
  210.                             else
  211.                             {
  212.                                 TraceMsg(TF_WARNING, "hb: Could not create task!");
  213.                             }
  214.                         }
  215.                         else
  216.                         {
  217.                             TraceMsg(TF_WARNING, "hb: Could not get location on IExtractImage");
  218.                         }
  219.                         pei->Release();
  220.                     }
  221.                     psf->Release();
  222.                 }
  223.                 ILFree(pidl);
  224.             }
  225.         }
  226.     }
  227.     // make sure we are not still holding it...
  228.     ReleaseImageStore();
  229.     
  230.     return hr;
  231. }   // GetBitmap
  232. // private stuff
  233. HRESULT CThumbnail::UpdateLogoCallback(DWORD dwItem, int iIcon, HBITMAP hImage, LPCWSTR pszCache, BOOL fCache)
  234. {
  235.     if (!PostMessage(_hwnd, _uMsg, dwItem, (LPARAM)hImage))
  236.     {
  237.         DeleteObject(hImage);
  238.     }
  239.     return S_OK;
  240. }
  241. REFTASKOWNERID CThumbnail::GetTOID()    
  242.     return TOID_Thumbnail;
  243. }
  244. BOOL CThumbnail::IsItInCache( LPCWSTR pszItemPath, LPCWSTR pszGLocation, const FILETIME * pftDateStamp )
  245. {
  246.     LPPERSISTFILE pFile;
  247.     WCHAR szName[MAX_PATH];
  248.     BOOL fRes = FALSE;
  249.     DWORD dwStoreLock;
  250.     
  251.     // use pszItemPath to find the cache.....
  252.     StrCpyNW( szName, pszItemPath, MAX_PATH );
  253.     PathRemoveFileSpecW( szName );
  254.     HRESULT hr = CoCreateInstance( CLSID_ShellThumbnailDiskCache, NULL, CLSCTX_INPROC, IID_IPersistFile, (void **) & pFile);
  255.     if (FAILED( hr ))
  256.     {
  257.         return FALSE;
  258.     }
  259.     hr = pFile->Load( szName, STGM_READ );
  260.     if ( SUCCEEDED( hr ))
  261.     {
  262.         hr = pFile->QueryInterface( IID_IShellImageStore, (void **) & _pImageStore );
  263.     }
  264.     if ( SUCCEEDED( hr ))
  265.     {
  266.         hr = _pImageStore->Open( STGM_READ, & dwStoreLock );
  267.     }
  268.     
  269.     pFile->Release();
  270.     
  271.     if ( FAILED( hr ))
  272.     {
  273.         return FALSE;
  274.     }
  275.     
  276.     FILETIME ftCacheDateStamp;
  277.     hr = _pImageStore->IsEntryInStore( pszGLocation, &ftCacheDateStamp );
  278.     if (( hr == S_OK ) && (!pftDateStamp || 
  279.         (pftDateStamp->dwLowDateTime == ftCacheDateStamp.dwLowDateTime && 
  280.          pftDateStamp->dwHighDateTime == ftCacheDateStamp.dwHighDateTime)))
  281.     {
  282.         fRes = TRUE;
  283.     }
  284.     _pImageStore->Close( &dwStoreLock );
  285.     
  286.     return fRes;
  287. }
  288. void CThumbnail::ReleaseImageStore()
  289. {
  290.     ATOMICRELEASE( _pImageStore );
  291. }
  292. ////////////////////////////////////////////////////////////////////////////////////
  293. HRESULT CDiskCacheTask_Create( CLogoBase * pView,
  294.                                LPSHELLIMAGESTORE pImageStore,
  295.                                LPCWSTR pszItem,
  296.                                LPCWSTR pszGLocation,
  297.                                DWORD dwItem,
  298.                                const SIZE * prgSize,
  299.                                LPRUNNABLETASK * ppTask )
  300. {
  301.     if ( !ppTask || !pView || !pszItem || !pszGLocation || !pImageStore || !prgSize )
  302.     {
  303.         return E_INVALIDARG;
  304.     }
  305.     CDiskCacheTask *pTask = new CDiskCacheTask;
  306.     if ( pTask == NULL )
  307.     {
  308.         return E_OUTOFMEMORY;
  309.     }
  310.     StrCpyW( pTask->_szItem, pszItem );
  311.     StrCpyW( pTask->_szGLocation, pszGLocation );
  312.     
  313.     pTask->_pView = pView;
  314.     pTask->_pImageStore = pImageStore;
  315.     pImageStore->AddRef();
  316.     pTask->_dwItem = dwItem;
  317.     pTask->m_rgSize = * prgSize;
  318.     
  319.     *ppTask = SAFECAST( pTask, IRunnableTask *);
  320.     return NOERROR;
  321. }
  322. STDMETHODIMP CDiskCacheTask::RunInitRT( )
  323. {
  324.     // otherwise, run the task ....
  325.     HBITMAP hBmp = NULL;
  326.     DWORD dwLock;
  327.     HRESULT hr = _pImageStore->Open (STGM_READ, &dwLock );
  328.     if ( SUCCEEDED( hr ))
  329.     {
  330.         // at this point, we assume that it IS in the cache, and we already have a read lock on the cache...
  331.         hr = _pImageStore->GetEntry( _szGLocation, STGM_READ, &hBmp );
  332.     
  333.         // release the lock, we don't need it...
  334.         _pImageStore->Close( &dwLock );
  335.     }
  336.     ATOMICRELEASE( _pImageStore );
  337.     PrepImage( &hBmp );
  338.     
  339.     _pView->UpdateLogoCallback( _dwItem, 0, hBmp, _szItem, TRUE );
  340.     // ensure we don't return the  "we've suspended" value...
  341.     if ( hr == E_PENDING )
  342.         hr = E_FAIL;
  343.         
  344.     return hr;
  345. }
  346. CDiskCacheTask::CDiskCacheTask()
  347.     : CRunnableTask( RTF_DEFAULT )
  348. {
  349. }
  350. CDiskCacheTask::~CDiskCacheTask()
  351. {
  352.     ATOMICRELEASE( _pImageStore );
  353. }
  354. HRESULT CDiskCacheTask::PrepImage( HBITMAP * phBmp )
  355. {
  356.     ASSERT( phBmp && *phBmp );
  357.     DIBSECTION rgDIB;
  358.     if ( !GetObject( *phBmp, sizeof( rgDIB ), &rgDIB ))
  359.     {
  360.         return E_FAIL;
  361.     }
  362.     // the disk cache only supports 32 Bpp DIBS now, so we can ignore the palette issue...
  363.     ASSERT( rgDIB.dsBm.bmBitsPixel == 32 );
  364.     
  365.     HBITMAP hBmpNew = NULL;
  366.     HPALETTE hPal = NULL;
  367.     if ( SHGetCurColorRes() == 8 )
  368.     {
  369.         hPal = SHCreateShellPalette( NULL );
  370.     }
  371.     
  372.     IScaleAndSharpenImage2 * pScale;
  373.     HRESULT hr = CoCreateInstance( CLSID_ThumbnailScaler,
  374.                            NULL,
  375.                            CLSCTX_INPROC_SERVER,
  376.                            IID_IScaleAndSharpenImage2,
  377.                            (void **) &pScale );
  378.     if ( SUCCEEDED( hr ))
  379.     {
  380.         hr = pScale->ScaleSharpen2((BITMAPINFO *) &rgDIB.dsBmih,
  381.                                     rgDIB.dsBm.bmBits,
  382.                                     &hBmpNew,
  383.                                     &m_rgSize,
  384.                                     SHGetCurColorRes(),
  385.                                     hPal,
  386.                                     0, FALSE );
  387.         pScale->Release();
  388.     }
  389.     DeletePalette( hPal );
  390.     
  391.     if ( SUCCEEDED (hr ) && hBmpNew )
  392.     {
  393.         DeleteObject( *phBmp );
  394.         *phBmp = hBmpNew;
  395.     }
  396.     return NOERROR;
  397. }
  398. #endif // !POSTPOSTSPLIT