/*++ Copyright (c) 2000 Microsoft Corporation Module Name: filestream.cpp Abstract: Implementation of IStream over a win32 file. Author: Michael J. Grier (MGrier) 23-Feb-2000 Revision History: --*/ #include "stdinc.h" #include #include "sxsp.h" #include "filestream.h" #include "SxsExceptionHandling.h" CFileStreamBase::CFileStreamBase() : m_cRef(0), m_hFile(INVALID_HANDLE_VALUE), m_grfMode(0) { } CFileStreamBase::~CFileStreamBase() { ASSERT_NTC(m_cRef == 0); if (m_hFile != INVALID_HANDLE_VALUE) { CSxsPreserveLastError ple; if ((m_grfMode & STGM_WRITE) == STGM_WRITE) ::FlushFileBuffers(m_hFile); ::CloseHandle(m_hFile); ple.Restore(); } } BOOL CFileStreamBase::OpenForWrite( PCWSTR pszPath, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); PARAMETER_CHECK(pszPath != NULL); INTERNAL_ERROR_CHECK(m_hFile == INVALID_HANDLE_VALUE); IFW32INVALIDHANDLE_ORIGINATE_AND_EXIT( m_hFile = ::CreateFileW( pszPath, GENERIC_WRITE, dwShareMode, NULL, dwCreationDisposition, // default value is CREATE_ALWAYS dwFlagsAndAttributes, NULL)); m_grfMode = STGM_WRITE | STGM_CREATE; FN_EPILOG } BOOL CFileStreamBase::OpenForRead( PCWSTR pszPath, const CImpersonationData &ImpersonationData, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes ) { DWORD dwWin32Error; return this->OpenForRead( pszPath, ImpersonationData, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes, dwWin32Error, 0); } BOOL CFileStreamBase::OpenForRead( PCWSTR pszPath, const CImpersonationData &ImpersonationData, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, DWORD &rdwLastError, SIZE_T cExceptionalLastErrors, ... ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); DWORD dwLastError = ERROR_INTERNAL_ERROR; CImpersonate impersonate(ImpersonationData); rdwLastError = ERROR_SUCCESS; PARAMETER_CHECK(pszPath != NULL); INTERNAL_ERROR_CHECK(m_hFile == INVALID_HANDLE_VALUE); IFW32FALSE_EXIT(impersonate.Impersonate()); ::FusionpSetLastWin32Error(ERROR_SUCCESS); m_hFile = ::CreateFileW( pszPath, GENERIC_READ, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); dwLastError = ::FusionpGetLastWin32Error(); IFW32FALSE_EXIT(impersonate.Unimpersonate()); m_grfMode = STGM_READ; if (m_hFile == INVALID_HANDLE_VALUE) { va_list ap; SIZE_T i = 0; if (dwLastError == ERROR_SUCCESS) { // // CreateFile always set lasterror to be 0 for an unexisted file even OPEN_EXISTING // for GENERIC_READ, Fusion expect ERROR_FILE_NOT_FOUND in this case for some reason // ::FusionpSetLastWin32Error(ERROR_FILE_NOT_FOUND); dwLastError = ERROR_FILE_NOT_FOUND; // reset lLastError } va_start(ap, cExceptionalLastErrors); for (i=0; iOnRefCountZero(); return ulRefCount; } HRESULT CFileStreamBase::QueryInterface( REFIID riid, PVOID *ppvObj ) { HRESULT hr = NOERROR; FN_TRACE_HR(hr); IUnknown *pIUnknown = NULL; if (ppvObj != NULL) *ppvObj = NULL; if (ppvObj == NULL) { hr = E_POINTER; goto Exit; } if ((riid == IID_IUnknown) || (riid == IID_ISequentialStream) || (riid == IID_IStream)) pIUnknown = static_cast(this); if (pIUnknown == NULL) { hr = E_NOINTERFACE; goto Exit; } pIUnknown->AddRef(); *ppvObj = pIUnknown; hr = NOERROR; Exit: return hr; } HRESULT CFileStreamBase::Read( void *pv, ULONG cb, ULONG *pcbRead ) { HRESULT hr = NOERROR; FN_TRACE_HR(hr); ULONG cbRead = 0; if (pcbRead != NULL) *pcbRead = 0; INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE); IFW32FALSE_ORIGINATE_AND_EXIT(::ReadFile(m_hFile, pv, cb, &cbRead, NULL)); ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_VERBOSE, "SXS.DLL: CFileStreamBase::Read() got %d bytes from file.\n", cbRead); if (cbRead == 0) hr = S_FALSE; else hr = NOERROR; if (pcbRead != NULL) *pcbRead = cbRead; Exit: return hr; } HRESULT CFileStreamBase::Write( void const *pv, ULONG cb, ULONG *pcbWritten ) { HRESULT hr = NOERROR; FN_TRACE_HR(hr); ULONG cbWritten = 0; if (pcbWritten != NULL) *pcbWritten = 0; INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE); if (!::WriteFile(m_hFile, pv, cb, &cbWritten, NULL)) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: CFileStreamBase::Write() calling ::WriteFile() failed; ::FusionpGetLastWin32Error() = %d\n", ::FusionpGetLastWin32Error()); hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error()); goto Exit; } ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_VERBOSE, "SXS.DLL: CFileStreamBase::Write() got %d bytes from file.\n", cbWritten); if (cbWritten == 0) hr = S_FALSE; else hr = NOERROR; if (pcbWritten != NULL) *pcbWritten = cbWritten; Exit: return hr; } HRESULT CFileStreamBase::Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition ) { HRESULT hr = NOERROR; FN_TRACE_HR(hr); DWORD dwWin32Origin = 0; INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE); switch (dwOrigin) { default: hr = E_INVALIDARG; goto Exit; case STREAM_SEEK_SET: dwWin32Origin = FILE_BEGIN; break; case STREAM_SEEK_CUR: dwWin32Origin = FILE_CURRENT; break; case STREAM_SEEK_END: dwWin32Origin = FILE_END; break; } if (!::SetFilePointerEx( m_hFile, dlibMove, (LARGE_INTEGER *) plibNewPosition, dwWin32Origin)) { hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error()); goto Exit; } hr = NOERROR; Exit: return hr; } HRESULT CFileStreamBase::SetSize( ULARGE_INTEGER libNewSize ) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::SetSize() !!! NOT IMPLEMENTED !!!\n"); UNUSED(libNewSize); return E_NOTIMPL; } HRESULT CFileStreamBase::CopyTo( IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten ) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::CopyTo() !!! NOT IMPLEMENTED !!!\n"); if (pcbRead != NULL) pcbRead->QuadPart = 0; if (pcbWritten != NULL) pcbWritten->QuadPart = 0; return E_NOTIMPL; } HRESULT CFileStreamBase::Commit( DWORD grfCommitFlags ) { HRESULT hr = NOERROR; ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_INFO, "SXS.DLL: Entered CFileStreamBase::Commit()\n"); if (grfCommitFlags != 0) return E_INVALIDARG; if ( !Close()) hr = HRESULT_FROM_WIN32 (::FusionpGetLastWin32Error()); if (!SUCCEEDED(hr)) ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: %s() failed; ::FusionpGetLastWin32Error() = %d\n", __FUNCTION__, ::FusionpGetLastWin32Error()); else ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_INFO, "SXS.DLL: Leaving %s()\n", __FUNCTION__); return hr ; } HRESULT CFileStreamBase::Revert() { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::Revert() !!! NOT IMPLEMENTED !!!\n"); return E_NOTIMPL; } HRESULT CFileStreamBase::LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType ) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::LockRegion() !!! NOT IMPLEMENTED !!!\n"); UNUSED(libOffset); UNUSED(cb); UNUSED(dwLockType); return E_NOTIMPL; } HRESULT CFileStreamBase::UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType ) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::UnlockRegion() !!! NOT IMPLEMENTED !!!\n"); UNUSED(libOffset); UNUSED(cb); UNUSED(dwLockType); return E_NOTIMPL; } HRESULT CFileStreamBase::Stat( STATSTG *pstatstg, DWORD grfStatFlag ) { HRESULT hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); FN_TRACE_HR(hr); BY_HANDLE_FILE_INFORMATION bhfi; if (pstatstg != NULL) memset(pstatstg, 0, sizeof(*pstatstg)); PARAMETER_CHECK(((grfStatFlag & ~(STATFLAG_NONAME)) == 0)); PARAMETER_CHECK(pstatstg != NULL); if (!(grfStatFlag & STATFLAG_NONAME)) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: %s() does not handle STATFLAG_NONE; returning E_NOTIMPL.\n", __FUNCTION__); hr = E_NOTIMPL; goto Exit; } INTERNAL_ERROR_CHECK(m_hFile != INVALID_HANDLE_VALUE); IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileInformationByHandle(m_hFile, &bhfi)); pstatstg->pwcsName = NULL; pstatstg->type = STGTY_STREAM; pstatstg->cbSize.LowPart = bhfi.nFileSizeLow; pstatstg->cbSize.HighPart = bhfi.nFileSizeHigh; pstatstg->mtime = bhfi.ftLastWriteTime; pstatstg->ctime = bhfi.ftCreationTime; pstatstg->atime = bhfi.ftLastAccessTime; pstatstg->grfMode = m_grfMode; pstatstg->grfLocksSupported = LOCK_WRITE; pstatstg->clsid = GUID_NULL; pstatstg->grfStateBits = 0; pstatstg->reserved = 0; hr = NOERROR; Exit: return hr; } HRESULT CFileStreamBase::Clone( IStream **ppIStream ) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Entered CFileStreamBase::Clone() !!! NOT IMPLEMENTED !!!\n"); if (ppIStream != NULL) *ppIStream = NULL; return E_NOTIMPL; }