#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;
};