You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
474 lines
10 KiB
474 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stream.cpp
|
|
|
|
Abstract:
|
|
|
|
This module contains the implementation for the Server
|
|
Extension Object CSEOStream class.
|
|
|
|
Author:
|
|
|
|
Don Dumitru ([email protected])
|
|
|
|
Revision History:
|
|
|
|
dondu 03/29 created
|
|
|
|
--*/
|
|
|
|
|
|
// stream.cpp : Implementation of CSEOStream
|
|
#include "stdafx.h"
|
|
#include "seodefs.h"
|
|
#include "stream.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSEOStream
|
|
|
|
|
|
HRESULT CSEOStream::FinalConstruct() {
|
|
HRESULT hrRes;
|
|
TraceFunctEnter("CSEOStream::FinalConstruct");
|
|
|
|
m_hFile = NULL;
|
|
m_pszFile = NULL;
|
|
m_hEvent = NULL;
|
|
m_pSubStream = NULL;
|
|
hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
|
|
_ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
|
|
TraceFunctLeave();
|
|
return (SUCCEEDED(hrRes)?S_OK:hrRes);
|
|
}
|
|
|
|
|
|
void CSEOStream::FinalRelease() {
|
|
TraceFunctEnter("CSEOStream::FinalRelease");
|
|
|
|
Cleanup();
|
|
m_pUnkMarshaler.Release();
|
|
TraceFunctLeave();
|
|
}
|
|
|
|
|
|
void CSEOStream::Cleanup() {
|
|
|
|
if (m_hFile) {
|
|
CloseHandle(m_hFile);
|
|
m_hFile = NULL;
|
|
}
|
|
if (m_pszFile) {
|
|
CoTaskMemFree(m_pszFile);
|
|
m_pszFile = NULL;
|
|
}
|
|
if (m_hEvent) {
|
|
CloseHandle(m_hEvent);
|
|
m_hEvent = NULL;
|
|
}
|
|
if (m_pSubStream) {
|
|
m_pSubStream->Release();
|
|
m_pSubStream = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::Init(HANDLE hFile, LPCSTR pszFile, ULARGE_INTEGER libOffset, CSEOStream *pSubStream) {
|
|
|
|
Cleanup();
|
|
if (pSubStream) {
|
|
m_pSubStream = pSubStream;
|
|
m_pSubStream->AddRef();
|
|
} else {
|
|
if (hFile) {
|
|
if (!DuplicateHandle(GetCurrentProcess(),
|
|
hFile,
|
|
GetCurrentProcess(),
|
|
&m_hFile,
|
|
0,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS)) {
|
|
HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
Cleanup();
|
|
return (hrRes);
|
|
}
|
|
}
|
|
if (pszFile) {
|
|
DWORD dwLen;
|
|
|
|
dwLen = GetFullPathName(pszFile,0,NULL,NULL);
|
|
if (!dwLen) {
|
|
HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
Cleanup();
|
|
return (hrRes);
|
|
}
|
|
m_pszFile = (LPSTR) CoTaskMemAlloc((dwLen+1)*sizeof(*m_pszFile));
|
|
if (!m_pszFile) {
|
|
Cleanup();
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
dwLen = GetFullPathName(pszFile,dwLen+1,m_pszFile,NULL);
|
|
if (!dwLen) {
|
|
HRESULT hrRes = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
Cleanup();
|
|
return (hrRes);
|
|
}
|
|
}
|
|
}
|
|
m_libOffset = libOffset;
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::Init(HANDLE hFile, LPCWSTR pszFile, ULARGE_INTEGER libOffset, CSEOStream *pSubStream) {
|
|
USES_CONVERSION;
|
|
|
|
return (Init(hFile,W2A(pszFile),libOffset,pSubStream));
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::Open() {
|
|
|
|
if ((m_hFile && m_hEvent) || m_pSubStream) {
|
|
return (S_OK);
|
|
}
|
|
if (!m_hEvent) {
|
|
m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
|
|
if (!m_hEvent) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
if (m_hFile) {
|
|
return (S_OK);
|
|
}
|
|
}
|
|
if (!m_pszFile) {
|
|
return (OLE_E_BLANK);
|
|
}
|
|
m_hFile = CreateFile(m_pszFile,
|
|
GENERIC_READ|GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
if (m_hFile == INVALID_HANDLE_VALUE) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::ReadOffset(void *pv, ULONG cb, ULONG *pcbRead, ULARGE_INTEGER *plibOffset) {
|
|
HRESULT hrRes;
|
|
BOOL bRes;
|
|
DWORD cbRead;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
if (m_pSubStream) {
|
|
return (m_pSubStream->ReadOffset(pv,cb,pcbRead,plibOffset));
|
|
}
|
|
OVERLAPPED ov = {0,0,plibOffset->LowPart,plibOffset->HighPart,m_hEvent};
|
|
bRes = ReadFile(m_hFile,pv,cb,&cbRead,&ov);
|
|
if (!bRes) {
|
|
|
|
switch (GetLastError()) {
|
|
|
|
case ERROR_HANDLE_EOF:
|
|
cbRead = 0;
|
|
break;
|
|
|
|
case ERROR_IO_PENDING:
|
|
if (!GetOverlappedResult(m_hFile,&ov,&cbRead,TRUE)) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
}
|
|
plibOffset->QuadPart += cbRead;
|
|
if (pcbRead) {
|
|
*pcbRead = cbRead;
|
|
}
|
|
return (cbRead?S_OK:S_FALSE);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Read(void *pv, ULONG cb, ULONG *pcbRead) {
|
|
|
|
return (ReadOffset(pv,cb,pcbRead,&m_libOffset));
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::WriteOffset(void const* pv, ULONG cb, ULONG *pcbWritten, ULARGE_INTEGER *plibOffset) {
|
|
HRESULT hrRes;
|
|
BOOL bRes;
|
|
DWORD cbWritten;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
if (m_pSubStream) {
|
|
return (m_pSubStream->WriteOffset(pv,cb,pcbWritten,plibOffset));
|
|
}
|
|
OVERLAPPED ov = {0,0,plibOffset->LowPart,plibOffset->HighPart,m_hEvent};
|
|
bRes = WriteFile(m_hFile,pv,cb,&cbWritten,&ov);
|
|
if (!bRes) {
|
|
|
|
switch (GetLastError()) {
|
|
|
|
case ERROR_HANDLE_EOF:
|
|
cbWritten = 0;
|
|
break;
|
|
|
|
case ERROR_IO_PENDING:
|
|
if (!GetOverlappedResult(m_hFile,&ov,&cbWritten,TRUE)) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
}
|
|
plibOffset->QuadPart += cbWritten;
|
|
if (pcbWritten) {
|
|
*pcbWritten = cbWritten;
|
|
}
|
|
return ((cbWritten==cb)?S_OK:STG_E_MEDIUMFULL);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Write(void const* pv, ULONG cb, ULONG *pcbWritten) {
|
|
|
|
return (WriteOffset(pv,cb,pcbWritten,&m_libOffset));
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::GetSize(ULARGE_INTEGER *plibSize) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
if (m_pSubStream) {
|
|
return (m_pSubStream->GetSize(plibSize));
|
|
}
|
|
if (!plibSize) {
|
|
return (E_POINTER);
|
|
}
|
|
plibSize->LowPart = GetFileSize(m_hFile,&plibSize->HighPart);
|
|
if ((plibSize->LowPart == 0xffffffff) && (GetLastError() != NO_ERROR)) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *pdlibNewPosition) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = S_OK;
|
|
switch (dwOrigin) {
|
|
|
|
case STREAM_SEEK_SET:
|
|
if (dlibMove.QuadPart < 0) {
|
|
hrRes = E_INVALIDARG;
|
|
break;
|
|
}
|
|
m_libOffset.QuadPart = (DWORDLONG) dlibMove.QuadPart;
|
|
break;
|
|
|
|
case STREAM_SEEK_CUR:
|
|
if ((dlibMove.QuadPart < 0) && ((DWORDLONG) -dlibMove.QuadPart > m_libOffset.QuadPart)) {
|
|
hrRes = E_INVALIDARG;
|
|
break;
|
|
}
|
|
m_libOffset.QuadPart = (DWORDLONG) ((LONGLONG) m_libOffset.QuadPart + dlibMove.QuadPart);
|
|
break;
|
|
|
|
case STREAM_SEEK_END:
|
|
ULARGE_INTEGER libSize;
|
|
|
|
hrRes = GetSize(&libSize);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
if ((dlibMove.QuadPart < 0) && ((DWORDLONG) -dlibMove.QuadPart > libSize.QuadPart)) {
|
|
hrRes = E_INVALIDARG;
|
|
break;
|
|
}
|
|
m_libOffset.QuadPart = (DWORDLONG) ((LONGLONG) libSize.QuadPart + dlibMove.QuadPart);
|
|
break;
|
|
|
|
default:
|
|
hrRes = STG_E_INVALIDFUNCTION;
|
|
break;
|
|
}
|
|
if (pdlibNewPosition) {
|
|
*pdlibNewPosition = m_libOffset;
|
|
}
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::SetSize(ULARGE_INTEGER libNewSize) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
if (m_pSubStream) {
|
|
return (m_pSubStream->SetSize(libNewSize));
|
|
}
|
|
if ((SetFilePointer(m_hFile,libNewSize.LowPart,(LONG *) &libNewSize.HighPart,FILE_BEGIN) == 0xffff) &&
|
|
(GetLastError() != NO_ERROR)) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
if (!SetEndOfFile(m_hFile)) {
|
|
return (HRESULT_FROM_WIN32(GetLastError()));
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::CopyToOffset(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten, ULARGE_INTEGER *plibOffset) {
|
|
HRESULT hrRes;
|
|
LPVOID pv;
|
|
ULARGE_INTEGER cbRead;
|
|
ULARGE_INTEGER cbWritten;
|
|
|
|
if (!pstm) {
|
|
return (E_POINTER);
|
|
}
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
pv = alloca((DWORD) min(cb.QuadPart,4096));
|
|
if (!pv) {
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
cbRead.QuadPart = 0;
|
|
cbWritten.QuadPart = 0;
|
|
while (1) {
|
|
DWORD cbTmpRead;
|
|
DWORD cbTmpWrite;
|
|
|
|
if (!cb.QuadPart) {
|
|
hrRes = S_OK;
|
|
break;
|
|
}
|
|
cbTmpRead = 0;
|
|
hrRes = ReadOffset(pv,(DWORD) min(cb.QuadPart,4096),&cbTmpRead,plibOffset);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
if (cbTmpRead == 0) {
|
|
hrRes = S_FALSE;
|
|
break;
|
|
}
|
|
cbRead.QuadPart += cbTmpRead;
|
|
cbTmpWrite = 0;
|
|
hrRes = pstm->Write(pv,cbTmpRead,&cbTmpWrite);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
if (hrRes == STG_E_MEDIUMFULL) {
|
|
cbWritten.QuadPart += cbTmpWrite;
|
|
}
|
|
break;
|
|
}
|
|
cbWritten.QuadPart += cbTmpWrite;
|
|
cb.QuadPart -= cbTmpRead;
|
|
}
|
|
if (pcbRead) {
|
|
*pcbRead = cbRead;
|
|
}
|
|
if (pcbWritten) {
|
|
*pcbWritten = cbWritten;
|
|
}
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) {
|
|
|
|
return (CopyToOffset(pstm,cb,pcbRead,pcbWritten,&m_libOffset));
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Commit(DWORD grfCommitFlags) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Revert(void) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Stat(STATSTG * pstatstg, DWORD grfStatFlag) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT CSEOStream::CloneOffset(IStream **pstm, ULARGE_INTEGER libOffset) {
|
|
HRESULT hrRes;
|
|
|
|
if (!SUCCEEDED(hrRes=Open())) {
|
|
return (hrRes);
|
|
}
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE CSEOStream::Clone(IStream **pstm) {
|
|
|
|
return (CloneOffset(pstm,m_libOffset));
|
|
}
|