1 |
#ifndef FILE_STREAM_H__
|
2 |
#define FILE_STREAM_H__
|
3 |
/* This class was copied from the MSDN docs */
|
4 |
|
5 |
//implement filestream that derives from IStream
|
6 |
class FileStream : public IStream
|
7 |
{
|
8 |
FileStream(HANDLE hFile)
|
9 |
{
|
10 |
_refcount = 1;
|
11 |
_hFile = hFile;
|
12 |
}
|
13 |
|
14 |
~FileStream()
|
15 |
{
|
16 |
if (_hFile != INVALID_HANDLE_VALUE)
|
17 |
{
|
18 |
::CloseHandle(_hFile);
|
19 |
}
|
20 |
}
|
21 |
|
22 |
public:
|
23 |
HRESULT static OpenFile(LPCWSTR pName, IStream ** ppStream, bool fWrite)
|
24 |
{
|
25 |
HANDLE hFile = ::CreateFileW(pName, fWrite ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ,
|
26 |
NULL, fWrite ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
27 |
|
28 |
if (hFile == INVALID_HANDLE_VALUE)
|
29 |
return HRESULT_FROM_WIN32(GetLastError());
|
30 |
|
31 |
*ppStream = new FileStream(hFile);
|
32 |
|
33 |
if(*ppStream == NULL)
|
34 |
CloseHandle(hFile);
|
35 |
|
36 |
return S_OK;
|
37 |
}
|
38 |
|
39 |
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject)
|
40 |
{
|
41 |
if (iid == __uuidof(IUnknown)
|
42 |
|| iid == __uuidof(IStream)
|
43 |
|| iid == __uuidof(ISequentialStream))
|
44 |
{
|
45 |
*ppvObject = static_cast<IStream*>(this);
|
46 |
AddRef();
|
47 |
return S_OK;
|
48 |
} else
|
49 |
return E_NOINTERFACE;
|
50 |
}
|
51 |
|
52 |
virtual ULONG STDMETHODCALLTYPE AddRef(void)
|
53 |
{
|
54 |
ULONG res = (ULONG)InterlockedIncrement(&_refcount);
|
55 |
ATLTRACE("FileStream::AddRef refcnt = %lu\n", res);
|
56 |
return res;
|
57 |
}
|
58 |
|
59 |
virtual ULONG STDMETHODCALLTYPE Release(void)
|
60 |
{
|
61 |
ULONG res = (ULONG) InterlockedDecrement(&_refcount);
|
62 |
ATLTRACE("FileStream::Release refcnt = %lu\n", res);
|
63 |
|
64 |
if (res == 0)
|
65 |
delete this;
|
66 |
return res;
|
67 |
}
|
68 |
|
69 |
// ISequentialStream Interface
|
70 |
public:
|
71 |
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead)
|
72 |
{
|
73 |
BOOL rc = ReadFile(_hFile, pv, cb, pcbRead, NULL);
|
74 |
return (rc) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
75 |
}
|
76 |
|
77 |
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG* pcbWritten)
|
78 |
{
|
79 |
BOOL rc = WriteFile(_hFile, pv, cb, pcbWritten, NULL);
|
80 |
return rc ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
81 |
}
|
82 |
|
83 |
// IStream Interface
|
84 |
public:
|
85 |
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER)
|
86 |
{
|
87 |
return E_NOTIMPL;
|
88 |
}
|
89 |
|
90 |
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*,
|
91 |
ULARGE_INTEGER*)
|
92 |
{
|
93 |
return E_NOTIMPL;
|
94 |
}
|
95 |
|
96 |
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD)
|
97 |
{
|
98 |
return E_NOTIMPL;
|
99 |
}
|
100 |
|
101 |
virtual HRESULT STDMETHODCALLTYPE Revert(void)
|
102 |
{
|
103 |
return E_NOTIMPL;
|
104 |
}
|
105 |
|
106 |
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
|
107 |
{
|
108 |
return E_NOTIMPL;
|
109 |
}
|
110 |
|
111 |
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
|
112 |
{
|
113 |
return E_NOTIMPL;
|
114 |
}
|
115 |
|
116 |
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **)
|
117 |
{
|
118 |
return E_NOTIMPL;
|
119 |
}
|
120 |
|
121 |
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin,
|
122 |
ULARGE_INTEGER* lpNewFilePointer)
|
123 |
{
|
124 |
DWORD dwMoveMethod;
|
125 |
|
126 |
switch(dwOrigin)
|
127 |
{
|
128 |
case STREAM_SEEK_SET:
|
129 |
dwMoveMethod = FILE_BEGIN;
|
130 |
break;
|
131 |
case STREAM_SEEK_CUR:
|
132 |
dwMoveMethod = FILE_CURRENT;
|
133 |
break;
|
134 |
case STREAM_SEEK_END:
|
135 |
dwMoveMethod = FILE_END;
|
136 |
break;
|
137 |
default:
|
138 |
return STG_E_INVALIDFUNCTION;
|
139 |
break;
|
140 |
}
|
141 |
|
142 |
if (SetFilePointerEx(_hFile, liDistanceToMove, (PLARGE_INTEGER) lpNewFilePointer,
|
143 |
dwMoveMethod) == 0)
|
144 |
return HRESULT_FROM_WIN32(GetLastError());
|
145 |
return S_OK;
|
146 |
}
|
147 |
|
148 |
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag)
|
149 |
{
|
150 |
if (GetFileSizeEx(_hFile, (PLARGE_INTEGER) &pStatstg->cbSize) == 0)
|
151 |
return HRESULT_FROM_WIN32(GetLastError());
|
152 |
return S_OK;
|
153 |
}
|
154 |
|
155 |
private:
|
156 |
HANDLE _hFile;
|
157 |
LONG _refcount;
|
158 |
};
|
159 |
|
160 |
#endif // FILE_STREAM_H__
|