1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6#include "stdafx.h" // Precompiled header key.
7#include "fstream.h"
8
9CFileStream::CFileStream()
10: _cRef(1)
11, _hFile(INVALID_HANDLE_VALUE)
12{
13}
14
15CFileStream::~CFileStream()
16{
17 Close();
18}
19
20HRESULT CFileStream::OpenForRead(LPCWSTR wzFilePath)
21{
22 HRESULT hr = S_OK;
23 DWORD dwShareMode = FILE_SHARE_READ;
24
25 dwShareMode |= FILE_SHARE_DELETE;
26
27 _ASSERTE(_hFile == INVALID_HANDLE_VALUE && wzFilePath);
28 if (_hFile != INVALID_HANDLE_VALUE || !wzFilePath) {
29 hr = E_INVALIDARG;
30 goto Exit;
31 }
32
33 _hFile = WszCreateFile(wzFilePath, GENERIC_READ,
34 dwShareMode, NULL,
35 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
36 if (_hFile == INVALID_HANDLE_VALUE) {
37 hr = HRESULT_FROM_WIN32(GetLastError());
38 goto Exit;
39 }
40
41Exit:
42 return hr;
43}
44
45HRESULT CFileStream::OpenForWrite(LPCWSTR wzFilePath)
46{
47 HRESULT hr = S_OK;
48
49 _ASSERTE(_hFile == INVALID_HANDLE_VALUE && wzFilePath);
50 if (_hFile != INVALID_HANDLE_VALUE || !wzFilePath) {
51 hr = E_INVALIDARG;
52 goto Exit;
53 }
54
55 _hFile = WszCreateFile(wzFilePath, GENERIC_WRITE,
56 FILE_SHARE_READ, NULL,
57 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
58
59 if (_hFile == INVALID_HANDLE_VALUE)
60 {
61 hr = HRESULT_FROM_WIN32(GetLastError());
62 goto Exit;
63 }
64
65Exit:
66 return hr;
67}
68
69HRESULT CFileStream::QueryInterface(REFIID riid, void **ppv)
70{
71 HRESULT hr = S_OK;
72
73 if (!ppv)
74 return E_POINTER;
75
76 *ppv = NULL;
77
78 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) {
79 *ppv = static_cast<IStream *>(this);
80 }
81 else {
82 hr = E_NOINTERFACE;
83 }
84
85 if (*ppv) {
86 AddRef();
87 }
88
89 return hr;
90}
91
92STDMETHODIMP_(ULONG) CFileStream::AddRef()
93{
94 return InterlockedIncrement(&_cRef);
95}
96
97STDMETHODIMP_(ULONG) CFileStream::Release()
98{
99 ULONG ulRef = InterlockedDecrement(&_cRef);
100
101 if (!ulRef) {
102 delete this;
103 }
104
105 return ulRef;
106}
107
108HRESULT CFileStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
109{
110 HRESULT hr = S_OK;
111 ULONG cbRead = 0;
112
113 if (pcbRead != NULL) {
114 *pcbRead = 0;
115 }
116
117 _ASSERTE(_hFile != INVALID_HANDLE_VALUE);
118 if (_hFile == INVALID_HANDLE_VALUE) {
119 hr = E_UNEXPECTED;
120 goto Exit;
121 }
122
123 if (!::ReadFile(_hFile, pv, cb, &cbRead, NULL)) {
124 hr = HRESULT_FROM_WIN32(::GetLastError());
125 goto Exit;
126 }
127
128 if (cbRead == 0) {
129 hr = S_FALSE;
130 }
131 else {
132 hr = NOERROR;
133 }
134
135 if (pcbRead != NULL) {
136 *pcbRead = cbRead;
137 }
138
139Exit:
140 return hr;
141}
142
143HRESULT CFileStream::Write(void const *pv, ULONG cb, ULONG *pcbWritten)
144{
145 HRESULT hr = S_OK;
146 ULONG cbWritten = 0;
147
148 if (pcbWritten != NULL) {
149 *pcbWritten = 0;
150 }
151
152 _ASSERTE(_hFile != INVALID_HANDLE_VALUE);
153 if (_hFile == INVALID_HANDLE_VALUE) {
154 hr = E_UNEXPECTED;
155 goto Exit;
156 }
157
158 if (!::WriteFile(_hFile, pv, cb, &cbWritten, NULL)) {
159 hr = HRESULT_FROM_WIN32(::GetLastError());
160 goto Exit;
161 }
162
163 if (cbWritten == 0) {
164 hr = S_FALSE;
165 }
166 else {
167 hr = S_OK;
168 }
169
170 if (pcbWritten != NULL) {
171 *pcbWritten = cbWritten;
172 }
173
174Exit:
175 return hr;
176}
177
178HRESULT CFileStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
179{
180#if 1 // SetFilePointerEx not supported on Win9x
181 return E_NOTIMPL;
182#else
183 HRESULT hr = S_OK;
184 DWORD dwFileOrigin;
185 BOOL bRet;
186
187 _ASSERTE(_hFile != INVALID_HANDLE_VALUE);
188 if (_hFile == INVALID_HANDLE_VALUE) {
189 hr = E_UNEXPECTED;
190 goto Exit;
191 }
192
193 switch (dwOrigin) {
194 case STREAM_SEEK_SET:
195 dwFileOrigin = FILE_BEGIN;
196 break;
197
198 case STREAM_SEEK_CUR:
199 dwFileOrigin = FILE_CURRENT;
200 break;
201
202 case STREAM_SEEK_END:
203 dwFileOrigin = FILE_END;
204 break;
205
206 default:
207 hr = E_UNEXPECTED;
208 goto Exit;
209 }
210
211 bRet = SetFilePointerEx(_hFile, dlibMove, (LARGE_INTEGER *)plibNewPosition,
212 dwFileOrigin);
213 if (!bRet) {
214 hr = HRESULT_FROM_WIN32(::GetLastError());
215 goto Exit;
216 }
217
218
219Exit:
220 return hr;
221#endif
222}
223
224HRESULT CFileStream::SetSize(ULARGE_INTEGER libNewSize)
225{
226 return E_NOTIMPL;
227}
228
229HRESULT CFileStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
230{
231 return E_NOTIMPL;
232}
233
234HRESULT CFileStream::Commit(DWORD grfCommitFlags)
235{
236 HRESULT hr = S_OK;
237
238 if (grfCommitFlags != 0) {
239 hr = E_INVALIDARG;
240 goto Exit;
241 }
242
243 if (!Close()) {
244 hr = HRESULT_FROM_WIN32(GetLastError());
245 }
246
247Exit:
248 return hr;
249}
250
251HRESULT CFileStream::Revert()
252{
253 return E_NOTIMPL;
254}
255
256HRESULT CFileStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
257{
258 return E_NOTIMPL;
259}
260
261HRESULT CFileStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
262{
263 return E_NOTIMPL;
264}
265
266HRESULT CFileStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
267{
268 return E_NOTIMPL;
269}
270
271HRESULT CFileStream::Clone(IStream **ppIStream)
272{
273 return E_NOTIMPL;
274}
275
276
277BOOL CFileStream::Close()
278{
279 BOOL fSuccess = FALSE;
280
281 if (_hFile != INVALID_HANDLE_VALUE) {
282 if (!::CloseHandle(_hFile)) {
283 _hFile = INVALID_HANDLE_VALUE;
284 goto Exit;
285 }
286
287 _hFile = INVALID_HANDLE_VALUE;
288 }
289
290 fSuccess = TRUE;
291
292Exit:
293 return fSuccess;
294}
295
296