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

Windows Kernel

Development Platform:

Visual C++

  1. /******************************Module*Header*******************************
  2. * Module Name: ctngen.cpp
  3. *
  4. * Implementation of the IThumbnailExtractor interface
  5. *
  6. * Created: 14-Nov-1997
  7. * Author: Ori Gershony [orig]
  8. *
  9. * Copyright (c) 1996 Microsoft Corporation
  10. **************************************************************************/
  11. #include "objbase.h"
  12. #include "stdafx.h"
  13. #include "tnail.h"
  14. #include "ctngen.h"
  15. extern CHAR THUMBNAIL_CLIPDATA[];
  16. //
  17. // Ntfs Flat File objects do not respond to QI for IID_IStorage any more.
  18. // If you really need an IStorage* and you are a system component then
  19. // you can use IID_IFlatStorage.  (IFlatStorage does not marshal)
  20. //
  21. EXTERN_C const IID IID_IFlatStorage = { /* b29d6138-b92f-11d1-83ee-00c04fc2c6d4 */
  22.     0xb29d6138,
  23.     0xb92f,
  24.     0x11d1,
  25.     {0x83, 0xee, 0x00, 0xc0, 0x4f, 0xc2, 0xc6, 0xd4}
  26.   };
  27. // Global critical section to make code single threaded.
  28. // Actually the code doesn't look to bad, but we are calling the JPG library
  29. // and I know nothing about that.  Perhaps with alot more thought, study and
  30. // investigation this code could be shown to be thread safe.
  31. //
  32. CRITICAL_SECTION g_csTNGEN;
  33. /******************************Public*Routine******************************
  34. * CThumbnailFCNContainer::CThumbnailFCNContainer
  35. *
  36. *   Constructor for CThumbnailFCNContainer
  37. *
  38. * Arguments:
  39. *
  40. * Return Value:
  41. *
  42. *     none
  43. *
  44. * History:
  45. *
  46. *     14-Nov-1997 -by- Ori Gershony [orig]
  47. *
  48. **************************************************************************/
  49. CThumbnailFCNContainer::CThumbnailFCNContainer(VOID)
  50. {
  51.     TN_Initialize();
  52. }
  53. /******************************Public*Routine******************************
  54. * CThumbnailFCNContainer::~CThumbnailFCNContainer
  55. *
  56. *   Destructor for CThumbnailFCNContainer
  57. *
  58. * Arguments:
  59. *
  60. * Return Value:
  61. *
  62. *     none
  63. *
  64. * History:
  65. *
  66. *     14-Nov-1997 -by- Ori Gershony [orig]
  67. *
  68. **************************************************************************/
  69. CThumbnailFCNContainer::~CThumbnailFCNContainer(VOID)
  70. {
  71.     TN_Uninitialize();
  72. }
  73. /******************************Public*Routine******************************
  74. * CThumbnailFCNContainer::OnFileUpdated
  75. *
  76. *   This method notifies us that the file indicated by pStg has been
  77. *   modified and therefore we should generate a new thumbnail for it.
  78. *
  79. * Arguments:
  80. *
  81. *     pStg -- A pointer to a storage of the file which was modified
  82. *
  83. * Return Value:
  84. *
  85. *     NOERROR upon success, or appropriate error code
  86. *
  87. * History:
  88. *
  89. *     14-Nov-1997 -by- Ori Gershony [orig]
  90. *
  91. **************************************************************************/
  92. STDMETHODIMP
  93. CThumbnailFCNContainer::OnFileUpdated(
  94.     IStorage *pStg
  95.     )
  96. {
  97.     HRESULT retVal;
  98.     IStream *pInputStream;
  99.     IPropertySetStorage *pPropSetStg=NULL;
  100.     //
  101.     // A little bit of validation won't hurt, and can protect us against
  102.     // bad callers
  103.     //
  104.     if (pStg == NULL)
  105.     {
  106.         return E_INVALIDARG;
  107.     }
  108.     EnterCriticalSection ( &g_csTNGEN );
  109.     //
  110.     // Get the PropertySetStorage Interface.  This also serves as the
  111.     // stablizing reference.
  112.     //
  113.     retVal = pStg->QueryInterface( IID_IPropertySetStorage,
  114.                                        (PVOID*)&pPropSetStg );
  115.     // if (FAILED(retVal))
  116.     // {
  117.     //     return retVal;
  118.     // }
  119.     // else
  120.     // {
  121.     //     VOID* pvData;
  122.     //     DWORD cbSize;
  123.     //
  124.     //     retVal = ReadThumbnail(&pvData, &cbSize, pPropSetStg );
  125.     //     if (SUCCEEDED(retVal))
  126.     //     {
  127.     //         CoTaskMemFree( pvData );
  128.     //     }
  129.     //     else
  130.     //     {
  131.     //         pPropSetStg->Release();
  132.     //         return S_OK;
  133.     //     }
  134.     // }
  135.     //
  136.     // First open the stream containing image data
  137.     //
  138.     retVal = pStg->OpenStream(L"CONTENTS",
  139.         NULL,
  140.         STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
  141.         0,
  142.         &pInputStream);
  143.     if (SUCCEEDED(retVal))
  144.     {
  145.         VOID *pBuffer = (VOID *) LocalAlloc (0, JPEG_BUFFER_SIZE);
  146.         if (pBuffer)
  147.         {
  148.             ULONG ulBufferSize;
  149.             FILETIME filetime = { 0 };
  150.             retVal = TN_GenerateCompressedThumbnail(pInputStream,
  151.                 (CHAR *) pBuffer,
  152.                 &ulBufferSize,
  153.                 filetime);
  154.             pInputStream->Release();
  155.             if (SUCCEEDED(retVal))
  156.             {
  157.                 retVal = WriteThumbnail(pBuffer, ulBufferSize, pPropSetStg, FALSE);
  158.             }
  159.             LocalFree(pBuffer);
  160.         }
  161.         else
  162.         {
  163.             //
  164.             // Release pInputStream if memory allocation fails.  We can't use a common
  165.             // code path for both because WriteThumbnail requires the stream to have already
  166.             // been released.
  167.             //
  168.             pInputStream->Release();
  169.         }
  170.     }
  171.     pPropSetStg->Release();
  172.     LeaveCriticalSection ( &g_csTNGEN );
  173.     return retVal;
  174. }
  175. /******************************Public*Routine******************************
  176. * CThumbnailFCNContainer::ExtractThumbnail
  177. *
  178. *   Returns a bitmap of the thumbnail for the storage pointed to by pStg
  179. *   Note:  The caller is responsible for freeing the bitmap pointed to by
  180. *          phOutputBitmap by calling DeleteObject!
  181. *
  182. * Arguments:
  183. *       pStg -- The storage containing the thumbnail
  184. *       ulLength -- The requested length
  185. *       ulWidth -- The requested width
  186. *       pulOutputLength -- will hold the actual output length
  187. *       pulOutputWidth -- will hold the actual output width
  188. *       phOutputBitmap -- A pointer that will point to the bitmap containing
  189. *           the thumbnail.  This will be released by the caller!
  190. *
  191. * Return Value:
  192. *
  193. *     NOERROR upon success, or appropriate error code
  194. *
  195. * History:
  196. *
  197. *     14-Nov-1997 -by- Ori Gershony [orig]
  198. *
  199. **************************************************************************/
  200. STDMETHODIMP
  201. CThumbnailFCNContainer::ExtractThumbnail(
  202.     IStorage *pStg,
  203.     ULONG ulLength,
  204.     ULONG ulHeight,
  205.     ULONG *pulOutputLength,
  206.     ULONG *pulOutputHeight,
  207.     HBITMAP *phOutputBitmap
  208.     )
  209. {
  210.     HRESULT retVal;
  211.     //
  212.     // A little bit of validation won't hurt, and can protect us against
  213.     // bad callers
  214.     //
  215.     if (pStg == NULL)
  216.     {
  217.         return E_INVALIDARG;
  218.     }
  219.     EnterCriticalSection ( &g_csTNGEN );
  220.     retVal = SuppressTimestampChanges(pStg);
  221.     if (SUCCEEDED(retVal))
  222.     {
  223.         retVal = ExtractThumbnailHelper(pStg,
  224.                 ulLength,
  225.                 ulHeight,
  226.                 pulOutputLength,
  227.                 pulOutputHeight,
  228.                 phOutputBitmap);
  229.     }
  230.     //
  231.     // If no thumbnail was extracted then generate a thumbnail
  232.     // and try again.
  233.     //
  234.     if (FAILED(retVal))
  235.     {
  236.         retVal = OnFileUpdated(pStg);
  237.         if (SUCCEEDED(retVal))
  238.         {
  239.             //
  240.             // Try again--now thumbnail should be there
  241.             //
  242.             retVal = ExtractThumbnailHelper(pStg,
  243.                 ulLength,
  244.                 ulHeight,
  245.                 pulOutputLength,
  246.                 pulOutputHeight,
  247.                 phOutputBitmap);
  248.         }
  249.     }
  250.     LeaveCriticalSection ( &g_csTNGEN );
  251.     return retVal;
  252. }
  253. /******************************Public*Routine******************************
  254. * CThumbnailFCNContainer::ExtractThumbnailHelper
  255. *
  256. *   Returns a bitmap of the thumbnail for the storage pointed to by pStg
  257. *   Note:  The caller is responsible for freeing the bitmap pointed to by
  258. *          phOutputBitmap by calling DeleteObject!
  259. *
  260. * Arguments:
  261. *       pStg -- The storage containing the thumbnail
  262. *       ulLength -- The requested length
  263. *       ulWidth -- The requested width
  264. *       pulOutputLength -- will hold the actual output length
  265. *       pulOutputWidth -- will hold the actual output width
  266. *       phOutputBitmap -- A pointer that will point to the bitmap containing
  267. *           the thumbnail.  This will be released by the caller!
  268. *
  269. * Return Value:
  270. *
  271. *     NOERROR upon success, or appropriate error code
  272. *
  273. * History:
  274. *
  275. *     14-Nov-1997 -by- Ori Gershony [orig]
  276. *
  277. **************************************************************************/
  278. STDMETHODIMP
  279. CThumbnailFCNContainer::ExtractThumbnailHelper(
  280.     IStorage *pStg,
  281.     ULONG ulLength,
  282.     ULONG ulHeight,
  283.     ULONG *pulOutputLength,
  284.     ULONG *pulOutputHeight,
  285.     HBITMAP *phOutputBitmap
  286.     )
  287. {
  288.     HRESULT retVal;
  289.     IPropertySetStorage *pPropSetStg;
  290.     //
  291.     // Read the thumbnail
  292.     //
  293.     VOID *pBuffer=NULL;
  294.     ULONG ulBufferSize=0;
  295.     retVal = pStg->QueryInterface( IID_IPropertySetStorage,
  296.                                    (PVOID*) & pPropSetStg );
  297.     if (SUCCEEDED(retVal))
  298.     {
  299.         retVal = ReadThumbnail(&pBuffer, &ulBufferSize, pPropSetStg);
  300.         if (SUCCEEDED(retVal))
  301.         {
  302.             retVal = TN_GenerateThumbnailImage(
  303.                  (CHAR *) pBuffer,
  304.                  ulLength,
  305.                  ulHeight,
  306.                  pulOutputLength,
  307.                  pulOutputHeight,
  308.                  phOutputBitmap);
  309.             CoTaskMemFree(pBuffer);
  310.         }
  311.         pPropSetStg->Release();
  312.     }
  313.     return retVal;
  314. }
  315. /******************************Public*Routine******************************
  316. * CThumbnailFCNContainer::GetTimeStamp
  317. *
  318. *   This method obtains the timestamp for the last modification of the CONTENTS
  319. *   stream of pStg
  320. *
  321. *
  322. * Arguments:
  323. *
  324. *     pStg -- A pointer to a storage of the file
  325. *     pFileTime -- A pointer to a variable which will receive the timestamp
  326. *
  327. * Return Value:
  328. *
  329. *     NOERROR upon success, or appropriate error code
  330. *
  331. * History:
  332. *
  333. *     30-Dec-1997 -by- Ori Gershony [orig]
  334. *
  335. **************************************************************************/
  336. STDMETHODIMP
  337. CThumbnailFCNContainer::GetTimeStamp(
  338.     IPropertySetStorage *pPropSetStg,
  339.     FILETIME *pFiletime
  340.     )
  341. {
  342.     //
  343.     // Obtain the timestamp
  344.     //
  345.     HRESULT retVal;
  346.     IStorage *pStg=NULL;
  347.     STATSTG statstg;
  348.     retVal = pPropSetStg->QueryInterface( IID_IFlatStorage, (PVOID*) & pStg );
  349.     if(SUCCEEDED(retVal))
  350.     {
  351.         retVal = pStg->Stat(&statstg, STATFLAG_NONAME);
  352.         if (SUCCEEDED(retVal))
  353.         {
  354.             *pFiletime = statstg.mtime;
  355.         }
  356.         pStg->Release();
  357.     }
  358.     return retVal;
  359. }
  360. /******************************Public*Routine******************************
  361. * CThumbnailFCNContainer::SuppressTimestampChanges
  362. *
  363. *   This method suppresses timestamp notifications for a storage
  364. *
  365. *
  366. * Arguments:
  367. *
  368. *     punkStorage -- A pointer to a storage of the file
  369. *
  370. * Return Value:
  371. *
  372. *     NOERROR upon success, or appropriate error code
  373. *
  374. * History:
  375. *
  376. *     30-Dec-1997 -by- Ori Gershony [orig]
  377. *
  378. **************************************************************************/
  379. STDMETHODIMP
  380. CThumbnailFCNContainer::SuppressTimestampChanges(
  381.     IUnknown *punkStorage
  382.     )
  383. {
  384.     HRESULT retVal;
  385.     //
  386.     // Supress file time modification
  387.     //
  388.     ITimeAndNoticeControl *pITimeAndNoticeControl;
  389.     retVal = punkStorage->QueryInterface(IID_ITimeAndNoticeControl,
  390.         (VOID **) &pITimeAndNoticeControl);
  391.     if (SUCCEEDED(retVal))
  392.     {
  393.         retVal = pITimeAndNoticeControl->SuppressChanges(1,0);
  394.         if (FAILED(retVal))
  395.             retVal = pITimeAndNoticeControl->SuppressChanges(0,0);
  396.         pITimeAndNoticeControl->Release();
  397.     }
  398.     return retVal;
  399. }