ファイルからストリーム(IStream)を作成 その2 (Emulate_SHCreateStreamOnFile)

IE5.0以上にあるSHLWAPIの同名の関数と互換
(2007.05.17)
#pragma once
 
// WAC.com Class Liblary for Visual C++
// Copyright (C) WAC.com Inc. All rights reserved.
//
// This file is a part of the WAC.com Class Liblary.
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
// which can be found in the file CPL.TXT at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.
 
// '07.05.09 : コードの整備 (sha)
// '07.05.17 : コードの整備 (sha)
 
#define _FILESTREAM_USE_EMULATE
 
#ifndef __ATLSOAP_H__
////////////////////////////////////////////////////////////////////////////////
//
// IStreamImpl - stub IStream implementation class
//
////////////////////////////////////////////////////////////////////////////////
 
class IStreamImpl : public IStream
{
public:
 
    HRESULT __stdcall Read(void * /*pDest*/, ULONG /*nMaxLen*/, ULONG * /*pnRead*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Write(const void * /*pv*/, ULONG /*cb*/, ULONG * /*pcbWritten*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Seek(LARGE_INTEGER /*dlibMove*/, DWORD /*dwOrigin*/, 
        ULARGE_INTEGER * /*pLibNewPosition*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall SetSize(ULARGE_INTEGER /*libNewSize*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall CopyTo(IStream * /*pStream*/, ULARGE_INTEGER /*cb*/, 
        ULARGE_INTEGER * /*pcbRead*/, ULARGE_INTEGER * /*pcbWritten*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Commit(DWORD /*grfCommitFlags*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Revert()
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall LockRegion(ULARGE_INTEGER /*libOffset*/, ULARGE_INTEGER /*cb*/, DWORD /*dwLockType*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall UnlockRegion(ULARGE_INTEGER /*libOffset*/, ULARGE_INTEGER /*cb*/, DWORD /*dwLockType*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Stat(STATSTG * /*pstatstg*/, DWORD /*grfStatFlag*/)
    {
        return E_NOTIMPL;
    }
 
    HRESULT __stdcall Clone(IStream ** /*ppstm*/)
    {
        return E_NOTIMPL;
    }
}; // class IStreamImpl
#endif
 
 
/////////////////////////////////////////////////////////////////////////////
// CFileStream
 
class ATL_NO_VTABLE CFileStream :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CFileStream, &CLSID_NULL>,
    //
    public IStreamImpl
{
protected:
    typedef CFileStream                            thisClass;
 
public:
    CFileStream()
    {
        m_hFile = INVALID_HANDLE_VALUE;
    }
    virtual ~CFileStream()
    {
        HRESULT hr = S_OK;
 
        if (m_hFile != INVALID_HANDLE_VALUE)
        {
            hr = this->Close();
            if (FAILED(hr))
            {
                // 無視する。。
            }
        }
    }
 
BEGIN_COM_MAP(CFileStream)
    COM_INTERFACE_ENTRY(ISequentialStream)
    COM_INTERFACE_ENTRY(IStream)
END_COM_MAP()
 
 
    DECLARE_PROTECT_FINAL_CONSTRUCT()
 
    HRESULT FinalConstruct()
    {
        return S_OK;
    }
    
    void FinalRelease() 
    {
     }
 
 
// ISequentialStream
public:
    STDMETHOD(Read)(void* pv, ULONG cb, ULONG* pcbRead)
    {
        if (pv == NULL)
        {
            return E_FAIL;
        }
        if (pcbRead == NULL)
        {
            return E_POINTER;
        }
 
        BOOL br = ::ReadFile(m_hFile, pv, cb, pcbRead, NULL);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    STDMETHOD(Write)(void const* pv, ULONG cb, ULONG* pcbWritten)
    {
        if (pv == NULL)
        {
            return E_FAIL;
        }
        if (pcbWritten == NULL)
        {
            return E_POINTER;
        }
 
        BOOL br = ::WriteFile(m_hFile, pv, cb, pcbWritten, NULL);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
 
// IStream
public:
    STDMETHOD(Seek)(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer)                
    {
        if (lpNewFilePointer == NULL)
        {
            return E_POINTER;
        }
 
        // Check to see if the origin is valid.
        DWORD dwMoveMethod = FILE_BEGIN;
        switch(dwOrigin)
        {
        case STREAM_SEEK_SET:
            dwMoveMethod = FILE_BEGIN;
            break;
        case STREAM_SEEK_CUR:
            dwMoveMethod = FILE_CURRENT;
            break;
        case STREAM_SEEK_END:
            dwMoveMethod = FILE_END;
            break;
        default:   
            return STG_E_INVALIDFUNCTION;
            break;
        }
 
        BOOL br = ::SetFilePointerEx(m_hFile, liDistanceToMove, (PLARGE_INTEGER)lpNewFilePointer, dwMoveMethod);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    STDMETHOD(Stat)(STATSTG* pStatstg, DWORD grfStatFlag) 
    {
        if (pStatstg == NULL)
        {
            return E_FAIL;
        }
 
        BOOL br = ::GetFileSizeEx(m_hFile, (PLARGE_INTEGER)&pStatstg->cbSize);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
 
public:
    #define STGM_ACCESS_MODE(stgm)                ((stgm)&0x0000f)
    #define STGM_SHARE_MODE(stgm)                ((stgm)&0x000f0)
    #define STGM_CREATE_MODE(stgm)                ((stgm)&0x0f000)
    HRESULT Create(LPCTSTR szFileName, DWORD grfMode, DWORD dwAttributes, BOOL fCreate, IStream *pstmTemplate)
    {
        if (m_hFile != INVALID_HANDLE_VALUE)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        if (grfMode & STGM_TRANSACTED)
        {
            return E_INVALIDARG;
        }
 
        DWORD dwDesiredAccess = 0;
        switch (STGM_ACCESS_MODE(grfMode))
        {
            case STGM_READWRITE:
            dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
            break;
        case STGM_WRITE:
            dwDesiredAccess = GENERIC_WRITE;
            break;
        case STGM_READ:
            dwDesiredAccess = GENERIC_READ;
            break;
        default:
            return E_INVALIDARG;
        }
 
        DWORD dwShareMode = 0;
        switch (STGM_SHARE_MODE(grfMode))
        {
            case STGM_SHARE_DENY_READ:
            dwShareMode = FILE_SHARE_WRITE;
            break;
        case STGM_SHARE_DENY_WRITE:
            dwShareMode = FILE_SHARE_READ;
            break;
        case STGM_SHARE_EXCLUSIVE:
            dwShareMode = 0;
            break;
        case STGM_SHARE_DENY_NONE:
            dwShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
            break;
        default:
            return E_INVALIDARG;
        }
 
        DWORD dwCreationDisposition = 0;
        switch (STGM_CREATE_MODE(grfMode))
        {
        case STGM_FAILIFTHERE:
            dwCreationDisposition = OPEN_EXISTING;
            break;
        case STGM_CREATE:
            dwCreationDisposition = CREATE_ALWAYS;
            break;
        default:
            return E_INVALIDARG;
        }
 
        DWORD dwFlagsAndAttributes = dwAttributes;
 
        m_hFile = ::CreateFile(szFileName, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
        if (m_hFile == INVALID_HANDLE_VALUE)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
    HRESULT Close()
    {
        if (m_hFile == INVALID_HANDLE_VALUE)
        {
            ATLASSERT(0);
            return E_FAIL;
        }
 
        BOOL br = ::CloseHandle(m_hFile);
        if (!br)
        {
            DWORD dwError = ::GetLastError();
            return HRESULT_FROM_WIN32(dwError);
        }
 
        return S_OK;
    }
 
public:
    // ファイルからIStream*を作成する
    // SHLWAPI 5.00 互換
    static HRESULT Emulate_SHCreateStreamOnFile(LPCTSTR szFileName, DWORD grfMode, IStream **ppstm)
    {
#ifdef _FILESTREAM_USE_EMULATE
        return thisClass::Emulate_SHCreateStreamOnFileEx(szFileName, grfMode, 0, FALSE, NULL, ppstm);
#else
        return ::SHCreateStreamOnFile(szFileName, grfMode, ppstm);
#endif
    }
    static HRESULT Emulate_SHCreateStreamOnFileEx(LPCTSTR szFileName, DWORD grfMode, DWORD dwAttributes, BOOL fCreate, IStream *pstmTemplate, IStream **ppstm)
    {
#ifdef _FILESTREAM_USE_EMULATE
        if (ppstm == NULL)
        {
            return E_POINTER;
        }
 
        HRESULT hr = S_OK;
 
        *ppstm = NULL;
 
        CComObject<CFileStream>* pFileStream = NULL;
        hr = CComObject<CFileStream>::CreateInstance(&pFileStream);
        if (FAILED(hr))
        {
            return hr;
        }
 
        hr = pFileStream->Create(szFileName, grfMode, dwAttributes, fCreate, pstmTemplate);
        if (FAILED(hr))
        {
            return hr;
        }
 
        *ppstm = (IStream*)pFileStream;
 
        return S_OK;
#else
        return ::SHCreateStreamOnFileEx(szFileName, grfMode, dwAttributes, fCreate, pstmTemplate, ppstm);
#endif
    }
 
protected:
    HANDLE m_hFile;
};
一覧に戻る
© 2003 WAC.com All Right Reserved.