社本@元ネオニート Blog

社本@元ネオニート (元々ワック) のいたずら書き (for Programmers)

AILight Banner
AILight Blog

プロフィール

社本@元ネオニート Blog
働いたら負けかなと思っていたのですが。。とうとう働き始めました。アメリカのシアトル・エリアにある企業向けのバックアップソフトを開発している会社です。日本人は私だけ。なんとか。。やっていけてるようです。

目次

Blog 利用状況

記事分類

過去の記事

タグ

ファイルを扱うIStreamの実装 - COM

XmlLiteのドキュメントの一部に、ファイルを扱うIStreamの実装例が載っていました。
そのままじゃつまらないので、ATL風に書き直してみました。

---
#pragma once

#include <atlsoap.h>       // IStreamImpl

/////////////////////////////////////////////////////////////////////////////
// CFileStream
class ATL_NO_VTABLE CFileStream :
 public CComObjectRootEx<CComSingleThreadModel>,
 public CComCoClass<CFILESTREAM, &CLSID_NULL>,
 //
 public IStreamImpl
{
public:
 CFileStream(HANDLE hFile = INVALID_HANDLE_VALUE)
 {
  m_hFile = hFile;
 }
 CFileStream(LPCTSTR szFileName, bool fWrite)
 {
  HRESULT hr = S_OK;

  hr = this->Create(szFileName, fWrite);
  if (FAILED(hr))
  {
   // 無視する。。
  }
 }
 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: HRESULT Create(LPCTSTR szFileName, bool fWrite) { if (m_hFile != INVALID_HANDLE_VALUE) { return E_FAIL; } DWORD dwDesiredAccess = (fWrite) ? GENERIC_WRITE : GENERIC_READ; DWORD dwShareMode = FILE_SHARE_READ; DWORD dwCreationDisposition = (fWrite) ? CREATE_ALWAYS : OPEN_EXISTING; DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 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) { return E_FAIL; } BOOL br = ::CloseHandle(m_hFile); if (!br) { DWORD dwError = ::GetLastError(); return HRESULT_FROM_WIN32(dwError); } return S_OK; } protected: HANDLE m_hFile; }; ---


■Default IStream Implementation - MSDN
http://windowssdk.msdn.microsoft.com/en-us/library/ms752876.aspx

投稿日時 : 2006年9月5日 1:22


コメントを追加

#  re: ファイルを扱うIStreamの実装 - COM 2006年9月13日 8:17 ms

ISequentialStreamのReadとWriteの第3引数はNULL可のようです。September 2005のドキュメントにはRead/Write、今のMSDNにはWriteにその記述があります。

#  re: ファイルを扱うIStreamの実装 - COM 2006年9月13日 13:07 社本@ワック

確かにそのようですね。直しておきますw
タイトル
名前
URL
コメント