/*****************************************************************************
 *
 *  (C) COPYRIGHT MICROSOFT CORPORATION, 1999 - 2000
 *
 *  TITLE:       image.cpp
 *
 *  VERSION:     1.0
 *
 *  AUTHOR:      RickTu
 *
 *  DATE:        9/16/99
 *
 *  DESCRIPTION: Image class that encapsulates stored images from the
 *               streaming video device.
 *
 *****************************************************************************/

#include <precomp.h>
#pragma hdrstop

CLSID g_clsidBMPEncoder = GUID_NULL;

using namespace Gdiplus;

/*****************************************************************************

   CImage constructor/desctructor

   <Notes>

 *****************************************************************************/

CImage::CImage(LPCTSTR     pszStillPath,
               BSTR        bstrRootFullItemName,
               LPCTSTR     pszPath,
               LPCTSTR     pszName,
               LONG        FolderType)
  : m_strRootPath(pszStillPath),
    m_strPathItem(pszPath),
    m_strName(pszName),
    m_bstrItemName(pszName),
    m_bstrRootFullItemName(bstrRootFullItemName),
    m_FolderType(FolderType),
    m_bImageTimeValid(FALSE),
    m_pThumb(NULL)
{
    DBG_FN("CImage::CImage");

    CSimpleStringWide str;
    CSimpleStringWide strName(m_bstrItemName);

    //
    // First, we need to strip off the extensions
    // from the appropriate places
    //

    strName = strName.Left(strName.ReverseFind( TEXT('.') ));

    m_bstrItemName = CSimpleBStr(strName);

    str = bstrRootFullItemName;
    str.Concat(L"\\");
    str += CSimpleStringWide(m_bstrItemName);

    m_bstrFullItemName = str.String();
}


CImage::~CImage()
{
    if (m_pThumb)
    {
        delete [] m_pThumb;
    }
}

/*****************************************************************************

   CImage::LoadImageInfo

   Loads information about the image such as its width, height, type, etc.

 *****************************************************************************/

STDMETHODIMP
CImage::LoadImageInfo( BYTE * pWiasContext )
{
    ASSERT(pWiasContext != NULL);

    HRESULT hr = S_OK;
    LONG    lBitsPerChannel     = 0;
    LONG    lBitsPerPixel       = 0;
    LONG    lWidth              = 0;
    LONG    lHeight             = 0;
    LONG    lChannelsPerPixel   = 0;
    LONG    lBytesPerLine       = 0;
    Bitmap  Image(CSimpleStringConvert::WideString(m_strPathItem));

    if (pWiasContext == NULL)
    {
        hr = E_POINTER;
        CHECK_S_OK2(hr, ("LoadImageInfo received a NULL pointer"));
        return hr;
    }
    else if (Image.GetLastStatus() != Ok)
    {
        hr = E_FAIL;
        CHECK_S_OK2(hr, ("CImage::LoadImageInfo failed to get the image information"
                         "for file '%ls'", CSimpleStringConvert::WideString(m_strPathItem)));

        return hr;
    }

    if (hr == S_OK)
    {
        PixelFormat lFormat;
        lFormat = Image.GetPixelFormat();

        if ((lFormat == PixelFormat16bppGrayScale) ||
            (lFormat == PixelFormat16bppRGB555)    ||
            (lFormat == PixelFormat16bppRGB565)    ||
            (lFormat == PixelFormat16bppARGB1555))
        {
            lBitsPerPixel   = 16;
            lBitsPerChannel = 5;   // this is actually not completely correct for RGB565, but anyway...
        }
        else if (lFormat == PixelFormat24bppRGB)
        {
            lBitsPerPixel   = 24;
            lBitsPerChannel = 8;
        }
        else if ((lFormat == PixelFormat32bppRGB)   ||
                 (lFormat == PixelFormat32bppARGB)  ||
                 (lFormat == PixelFormat32bppPARGB))
        {
            lBitsPerPixel   = 32;
            lBitsPerChannel = 10; // well, video cap won't have alpha in it, 
        }

        lWidth            = (LONG) Image.GetWidth();
        lHeight           = (LONG) Image.GetHeight();
        lChannelsPerPixel = 3;
        lBytesPerLine     = lWidth * (lBitsPerPixel / 8);
    }

    if (hr == S_OK)
    {
        PROPSPEC    propSpecs[7];
        PROPVARIANT propVars[7];

        ZeroMemory(&propSpecs, sizeof(propSpecs));

        // WIA_IPA_DATATYPE
        propSpecs[0].ulKind = PRSPEC_PROPID;
        propSpecs[0].propid = WIA_IPA_DATATYPE;
        propVars[0].vt      = VT_I4;
        propVars[0].lVal    = WIA_DATA_COLOR;

        // WIA_IPA_DEPTH
        propSpecs[1].ulKind = PRSPEC_PROPID;
        propSpecs[1].propid = WIA_IPA_DEPTH;
        propVars[1].vt      = VT_I4;
        propVars[1].lVal    = lBitsPerPixel;

        // WIA_IPA_PIXELS_PER_LINE
        propSpecs[2].ulKind = PRSPEC_PROPID;
        propSpecs[2].propid = WIA_IPA_PIXELS_PER_LINE;
        propVars[2].vt      = VT_I4;
        propVars[2].lVal    = lWidth;

        // WIA_IPA_NUMBER_OF_LINES
        propSpecs[3].ulKind = PRSPEC_PROPID;
        propSpecs[3].propid = WIA_IPA_NUMBER_OF_LINES;
        propVars[3].vt      = VT_I4;
        propVars[3].lVal    = lHeight;

        // WIA_IPA_CHANNELS_PER_PIXEL
        propSpecs[4].ulKind = PRSPEC_PROPID;
        propSpecs[4].propid = WIA_IPA_CHANNELS_PER_PIXEL;
        propVars[4].vt      = VT_I4;
        propVars[4].lVal    = lChannelsPerPixel;

        // WIA_IPA_BITS_PER_CHANNEL
        propSpecs[5].ulKind = PRSPEC_PROPID;
        propSpecs[5].propid = WIA_IPA_BITS_PER_CHANNEL;
        propVars[5].vt      = VT_I4;
        propVars[5].lVal    = lBitsPerChannel;

        // WIA_IPA_BYTES_PER_LINE
        propSpecs[6].ulKind = PRSPEC_PROPID;
        propSpecs[6].propid = WIA_IPA_BYTES_PER_LINE;
        propVars[6].vt      = VT_I4;
        propVars[6].lVal    = lBytesPerLine;

        // write the values of the properties.
        hr = wiasWriteMultiple(pWiasContext, 
                               sizeof(propVars) / sizeof(propVars[0]), 
                               propSpecs, 
                               propVars);

        CHECK_S_OK2(hr, ("CImage::LoadImageInfo, failed to write image properties"));
    }

    return hr;
}



/*****************************************************************************

   CImage::SetItemSize

   Call wia to calc new item size

 *****************************************************************************/

STDMETHODIMP
CImage::SetItemSize(BYTE                     * pWiasContext, 
                    MINIDRV_TRANSFER_CONTEXT * pDrvTranCtx)
{
    HRESULT                    hr;
    MINIDRV_TRANSFER_CONTEXT   drvTranCtx;
    GUID                       guidFormatID;
    BOOL                       bWriteProps = (pDrvTranCtx == NULL);

    DBG_FN("CImage::SetItemSize");

    ZeroMemory(&drvTranCtx, sizeof(MINIDRV_TRANSFER_CONTEXT));

    if (!pDrvTranCtx)
    {
        pDrvTranCtx = &drvTranCtx;
    }

    hr = wiasReadPropGuid(pWiasContext,
                          WIA_IPA_FORMAT,
                          (GUID*)&(pDrvTranCtx->guidFormatID),
                          NULL,
                          FALSE);

    CHECK_S_OK2(hr,("wiasReadPropGuid( WIA_IPA_FORMAT )"));

    if (FAILED(hr))
    {
        return hr;
    }

    hr = wiasReadPropLong( pWiasContext,
                           WIA_IPA_TYMED,
                           (LONG*)&(pDrvTranCtx->tymed),
                           NULL,
                           FALSE
                         );
    CHECK_S_OK2(hr,("wiasReadPropLong( WIA_IPA_TYMED )"));

    if (FAILED(hr))
    {
        return hr;
    }

    //
    // Wias works for DIB, and minidriver support native formats
    //

    if ((pDrvTranCtx->guidFormatID != WiaImgFmt_JPEG) &&
        (pDrvTranCtx->guidFormatID != WiaImgFmt_FLASHPIX) &&
        (pDrvTranCtx->guidFormatID != WiaImgFmt_TIFF))
    {
        //
        // Create the image from the file.
        //
        Bitmap BitmapImage(CSimpleStringConvert::WideString(m_strPathItem));
        if (Ok == BitmapImage.GetLastStatus())
        {
            //
            // Get the image's dimensions
            //
            UINT nSourceWidth = BitmapImage.GetWidth();
            UINT nSourceHeight = BitmapImage.GetHeight();
            if (nSourceWidth && nSourceHeight)
            {
                //
                // Fill in info for drvTranCtx
                //
                pDrvTranCtx->lCompression   = WIA_COMPRESSION_NONE;
                pDrvTranCtx->lWidthInPixels = nSourceWidth;
                pDrvTranCtx->lLines         = nSourceHeight;
                pDrvTranCtx->lDepth         = 24;

                hr = wiasGetImageInformation( pWiasContext, 0, pDrvTranCtx );

                //
                // We need to write out the item size based on
                // the JPEG converted to a BMP.  But we only need
                // to do this if the incoming context was NULL.
                //
                if (bWriteProps)
                {
                    hr = wiasWritePropLong( pWiasContext,
                                            WIA_IPA_ITEM_SIZE,
                                            pDrvTranCtx->lItemSize
                                          );
                    CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPA_ITEM_SIZE )"));

                    hr = wiasWritePropLong( pWiasContext,
                                            WIA_IPA_BYTES_PER_LINE,
                                            pDrvTranCtx->cbWidthInBytes
                                          );
                    CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPA_BYTES_PER_LINE )"));
                }

            }
            else
            {
                DBG_ERR(("nSourceWidth OR nSourceHeight were zero"));
                hr = E_FAIL;
            }

        }
        else
        {
            DBG_ERR(("Ok == BitmapImage.GetLastStatus failed"));
            hr = E_FAIL;
        }

    }
    else
    {

        CMappedView cmv( ActualImagePath(), 0, OPEN_EXISTING );

        LARGE_INTEGER liSize = cmv.FileSize();
        ULONG         ulSize;

        if (liSize.HighPart)
        {
            ulSize = 0;
            DBG_ERR(("The file was bigger than 4GB!!!"));
        }
        else
        {
            //
            // We could truncate here, I know, but that would have to be one huge file...
            // Anyway, the size wouldn't fit in te properties, which expects a LONG
            //
            ulSize = (ULONG)liSize.LowPart;
        }

        pDrvTranCtx->lItemSize      = ulSize;
        pDrvTranCtx->cbWidthInBytes = 0;

        if (bWriteProps)
        {
            //
            // We need to write out the item size based on the file size...
            //

            hr = wiasWritePropLong(pWiasContext,
                                   WIA_IPA_ITEM_SIZE,
                                   ulSize);

            CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPA_ITEM_SIZE )"));

            hr = wiasWritePropLong(pWiasContext,
                                   WIA_IPA_BYTES_PER_LINE,
                                   0);
        }

        CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPA_BYTES_PER_LINE )"));
    }

    CHECK_S_OK(hr);
    return hr;
}



/*****************************************************************************

   CImage::LoadThumbnail

   Loads (or creates if not already present) the thumbnail for this item.
   We also write the thumbnail as a property for this item.

 *****************************************************************************/

STDMETHODIMP
CImage::LoadThumbnail( BYTE * pWiasContext )
{

    HRESULT hr = E_FAIL;
    DBG_FN("CImage::LoadThumbnail");

    //
    // Only create the thumbnail if we haven't done so already
    //
    if (!m_pThumb)
    {
        Status StatusResult = Ok;

        //
        // Open the source image and make sure it is OK
        //
        Bitmap SourceImage( CSimpleStringConvert::WideString(m_strPathItem) );

        StatusResult = SourceImage.GetLastStatus();
        if (Ok == StatusResult)
        {

            //
            // Create the scaled bitmap and make sure it is OK
            //
            Bitmap ScaledImage(THUMB_WIDTH, THUMB_HEIGHT);

            StatusResult = ScaledImage.GetLastStatus();
            if (Ok == StatusResult)
            {
                //
                // Get a graphics to render the scaled image to and make sure it isn't NULL
                //
                Graphics *pScaledGraphics = Graphics::FromImage(&ScaledImage);
                if (pScaledGraphics)
                {
                    //
                    // Make sure it is valid
                    //
                    StatusResult = pScaledGraphics->GetLastStatus();
                    if (StatusResult == Ok)
                    {
                        //
                        // Draw the image scaled to thumbnail size
                        //
                        StatusResult = pScaledGraphics->DrawImage(&SourceImage, 0, 0, THUMB_WIDTH, THUMB_HEIGHT );
                        if (Ok == StatusResult)
                        {
                            //
                            // Create a bitmap to hold the flipped thumbnail and make sure it is OK
                            //
                            Bitmap FlippedImage(THUMB_WIDTH, THUMB_HEIGHT);

                            StatusResult = FlippedImage.GetLastStatus();
                            if (Ok == StatusResult)
                            {
                                //
                                // Create a graphics object to render the flipped image to and make sure it isn't NULL
                                //
                                Graphics *pFlippedGraphics = Graphics::FromImage(&FlippedImage);
                                if (pFlippedGraphics)
                                {
                                    //
                                    // Make sure it is valid
                                    //
                                    StatusResult = pFlippedGraphics->GetLastStatus();
                                    if (Ok == StatusResult)
                                    {
                                        //
                                        // Set up the parallelogram to flip the image
                                        //
                                        Point SourcePoints[3];
                                        SourcePoints[0].X = 0;
                                        SourcePoints[0].Y = THUMB_HEIGHT;
                                        SourcePoints[1].X = THUMB_WIDTH;
                                        SourcePoints[1].Y = THUMB_HEIGHT;
                                        SourcePoints[2].X = 0;
                                        SourcePoints[2].Y = 0;

                                        //
                                        // Draw the image, flipped
                                        //
                                        StatusResult = pFlippedGraphics->DrawImage(&ScaledImage, SourcePoints, 3);
                                        if (StatusResult == Ok)
                                        {
                                            //
                                            // Get the scaled and flipped image bits
                                            //
                                            Rect rcThumb( 0, 0, THUMB_WIDTH, THUMB_HEIGHT );
                                            BitmapData BitmapData;

// This ifdef is due to an API change in GDI+.  Notice
// that the first param to LockBits in the new version 
// takes a ptr to RECT.  Old version takes a reference
// to a RECT.
#ifdef DCR_USE_NEW_293849
                                            StatusResult = FlippedImage.LockBits( &rcThumb, ImageLockModeRead, PixelFormat24bppRGB, &BitmapData );
#else
                                            StatusResult = FlippedImage.LockBits( rcThumb, ImageLockModeRead, PixelFormat24bppRGB, &BitmapData );
#endif
                                            if (Ok == StatusResult)
                                            {
                                                //
                                                // Allocate the thumbnail data
                                                //
                                                m_pThumb = new BYTE[THUMB_SIZE_BYTES];
                                                if (m_pThumb)
                                                {
                                                    //
                                                    // Copy the thumbnail data over
                                                    //
                                                    CopyMemory( m_pThumb, BitmapData.Scan0, THUMB_SIZE_BYTES );
                                                }
                                                else
                                                {
                                                    hr = E_OUTOFMEMORY;
                                                    CHECK_S_OK2(hr, ("m_pThumb is NULL, couldn't allocate memory"));
                                                }
                                                //
                                                // Unlock the bits
                                                //
                                                FlippedImage.UnlockBits( &BitmapData );
                                            }
                                            else
                                            {
                                                DBG_ERR(("FlippedImage.LockBits( &rcThumb, ImageLockModeRead, PixelFormat24bppRGB, &BitmapData ) failed"));
                                            }
                                        }
                                        else
                                        {
                                            DBG_ERR(("pFlippedGraphics->DrawImage(&ScaledImage, SourcePoints, 3) failed"));
                                        }
                                    }
                                    else
                                    {
                                        DBG_ERR(("Ok == pFlippedGraphics->GetLastStatus() failed = '%d' (0x%08x)",
                                                 StatusResult, StatusResult));
                                    }
                                    //
                                    // Free the graphics object
                                    //
                                    delete pFlippedGraphics;
                                }
                                else
                                {
                                    DBG_ERR(("Graphics *pFlippedGraphics = Graphics::FromImage(&FlippedImage); returned NULL"));
                                }
                            }
                            else
                            {
                                DBG_ERR(("Ok == FlippedImage.GetLastStatus() failed = '%d',(0x%08x)",
                                         StatusResult, StatusResult));
                            }
                        }
                        else
                        {
                            DBG_ERR(("pScaledGraphics->DrawImage(&SourceImage, 0, 0, THUMB_WIDTH, THUMB_HEIGHT ) failed"));
                        }
                    }
                    else
                    {
                        DBG_ERR(("pScaledGraphics->GetLastStatus() failed = '%d' (0x%08x)",
                                 StatusResult, StatusResult));
                    }
                    //
                    // Free the graphics object
                    //
                    delete pScaledGraphics;
                }
                else
                {
                    DBG_ERR(("Graphics *pScaledGraphics = Graphics::FromImage(&ScaledImage); returned NULL"));
                }
            }
            else
            {
                DBG_ERR(("ScaledImage.GetLastStatus() failed = '%d' (0x%08x)",
                         StatusResult, StatusResult));
            }
        }
        else
        {
            DBG_ERR(("SourceImage.GetLastStatus() failed = '%d' (0x%08x)",
                     StatusResult, StatusResult));
        }
    }

    if (m_pThumb)
    {
        //
        // We have the bits, write them out as a property
        //

        PROPSPEC    propSpec;
        PROPVARIANT propVar;

        PropVariantInit(&propVar);

        propVar.vt          = VT_VECTOR | VT_UI1;
        propVar.caub.cElems = THUMB_SIZE_BYTES;
        propVar.caub.pElems = m_pThumb;

        propSpec.ulKind = PRSPEC_PROPID;
        propSpec.propid = WIA_IPC_THUMBNAIL;

        hr = wiasWriteMultiple(pWiasContext, 1, &propSpec, &propVar);
        CHECK_S_OK2(hr,("wiasWriteMultiple( WIA_IPC_THUMBNAIL )"));
    }
    else
    {
        if (SUCCEEDED(hr))
        {
            hr = E_FAIL;
        }
    }

    CHECK_S_OK(hr);
    return hr;
}


/*****************************************************************************

   CImage::InitImageInformation

   Called to initialize the properties for this image.  In the process,
   we also load (or create if needed) the thumbnail for this item.

 *****************************************************************************/

STDMETHODIMP
CImage::InitImageInformation(BYTE *pWiasContext,
                             LONG *plDevErrVal)
{
    HRESULT hr = S_OK;
    SYSTEMTIME st;


    DBG_FN("CImage::InitImageInformation");

    //
    // Use WIA services to set the extended property access and
    // valid value information from gWiaPropInfoDefaults.
    //

    hr = wiasSetItemPropAttribs( pWiasContext,
                                 NUM_CAM_ITEM_PROPS,
                                 gPropSpecDefaults,
                                 gWiaPropInfoDefaults
                               );
    //
    // Use WIA services to write image properties.
    //

    hr = wiasWritePropLong(pWiasContext, WIA_IPC_THUMB_WIDTH, ThumbWidth());
    CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPC_THUMB_WIDTH )"));

    hr = wiasWritePropLong(pWiasContext, WIA_IPC_THUMB_HEIGHT, ThumbHeight());
    CHECK_S_OK2(hr,("wiasWritePropLong( WIA_IPC_THUMB_HEIGHT )"));

    hr = wiasWritePropGuid(pWiasContext, WIA_IPA_PREFERRED_FORMAT, WiaImgFmt_JPEG);
    CHECK_S_OK2(hr,("wiasWritePropGuid( WIA_IPA_PREFERRED_FORMAT )"));

    GetImageTimeStamp( &st );
    hr = wiasWritePropBin( pWiasContext, WIA_IPA_ITEM_TIME, sizeof(SYSTEMTIME), (PBYTE)&st);
    CHECK_S_OK2(hr,("wiasWritePropBin( WIA_IPA_ITEM_TIME )"));

    //
    // calc item size
    //

    hr = SetItemSize(pWiasContext,NULL);
    CHECK_S_OK2(hr,("SetItemSize"));

    //
    // load thumbnail
    //

    hr = LoadThumbnail( pWiasContext );
    CHECK_S_OK2(hr,("LoadThumbnail"));

    //
    // Load additional image information such as the pixels per line, 
    // number of lines, etc.
    //
    hr = LoadImageInfo(pWiasContext);

    CHECK_S_OK2(hr,("wiaSetItemPropAttribs"));

    return hr;
}


/*****************************************************************************

   CImage::bstrItemName

   Returns the item name in the form of a BSTR.

 *****************************************************************************/

BSTR
CImage::bstrItemName()
{
    DBG_FN("CImage::bstrItemName");

    return m_bstrItemName;
}


/*****************************************************************************

   CImage::bstrFullItemName

   Returns the full item name in the form of a BSTR.

 *****************************************************************************/

BSTR
CImage::bstrFullItemName()
{
    DBG_FN("CImage::bstrFullItemName");

    return m_bstrFullItemName;
}



/*****************************************************************************

   CImage::ThumbWidth

   returns the thumbnail width

 *****************************************************************************/

LONG
CImage::ThumbWidth()
{
    DBG_FN("CImage::ThumbWidth");

    return THUMB_WIDTH;
}



/*****************************************************************************

   CImage::ThumbHeight

   returns the thumbnail height

 *****************************************************************************/

LONG
CImage::ThumbHeight()
{
    DBG_FN("CImage::ThumbHeight");

    return THUMB_HEIGHT;
}


/*****************************************************************************

   CImage::ImageTimeStamp

   returns creation time of image

 *****************************************************************************/

void
CImage::GetImageTimeStamp(SYSTEMTIME * pst)
{
    DBG_FN("CImage::ImageTimeStamp");

    if (!m_bImageTimeValid)
    {
        HANDLE hFile = CreateFile(m_strPathItem,
                                  GENERIC_READ,
                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
                                  NULL,
                                  OPEN_EXISTING,
                                  FILE_ATTRIBUTE_NORMAL,
                                  NULL);

        if (hFile != INVALID_HANDLE_VALUE)
        {
            FILETIME ft;

            if (GetFileTime( hFile, &ft, NULL, NULL ))
            {
                FILETIME ftLocal;

                if (FileTimeToLocalFileTime(&ft, &ftLocal))
                {
                    if (FileTimeToSystemTime( &ftLocal, &m_ImageTime ))
                    {

                        m_bImageTimeValid = TRUE;
                    }

                }

            }

            CloseHandle( hFile );
        }
        else
        {
            DBG_ERR(("CreateFile( %ls ) failed, GLE = %d",
                     m_strPathItem.String(), GetLastError()));

            //
            // default to filling in structure w/zeros
            //

            memset( pst, 0, sizeof(SYSTEMTIME) );
        }
    }

    if (m_bImageTimeValid && pst)
    {
        *pst = m_ImageTime;
    }
}



/*****************************************************************************

   CImage::ActualImagePath

   Returns filename path of actual image

 *****************************************************************************/

LPCTSTR
CImage::ActualImagePath()
{
    DBG_FN("CImage::ActualImagePath");

    return m_strPathItem.String();
}



/*****************************************************************************

   CImage::DoDelete

   Deletes the file (and thumbail) from the disk.

 *****************************************************************************/

HRESULT
CImage::DoDelete()
{
    HRESULT hr = S_OK;
    BOOL    bResFile;

    DBG_FN("CImage::DoDelete");

    //
    // Make sure we have a file to delete...
    //

    if (!m_strPathItem.Length())
    {
        DBG_ERR(("filename for item is zero length!"));
        hr = E_INVALIDARG;
    }
    else
    {
        //
        // We've got an item, so delete it and the thumbnail file
        //

        bResFile = DeleteFile(m_strPathItem.String());

        if (!bResFile)
        {
            DBG_ERR(("DeleteFile( %ls ) failed, GLE = %d",
                     m_strPathItem.String(),GetLastError()));
        }

        if (bResFile)
        {
            m_strPathItem           = NULL;
            m_strRootPath           = NULL;
            m_strName               = NULL;
            m_bstrRootFullItemName  = NULL;
            m_bstrFullItemName      = NULL;
            m_bImageTimeValid       = FALSE;
        }
        else
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }

    }

    CHECK_S_OK(hr);
    return hr;
}