/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership . The ASF licenses this file to you under the Apache
* License , Version 2 . 0 ( the " License " ) ; you may not use this file
* except in compliance with the License . You may obtain a copy of
* the License at http : //www.apache.org/licenses/LICENSE-2.0 .
*/
// TODO: StreamMode <-> AllocateMemory
#include <string.h>
#include <limits.h>
#ifdef _WIN32
#if !defined WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#include <osl/thread.h>
#include <tools/stream.hxx>
#include <o3tl/char16_t2wchar_t.hxx>
#include <osl/file.hxx>
using namespace osl;
static ErrCode GetSvError( DWORD nWntError )
{
static struct { DWORD wnt; ErrCode sv; } errArr[] =
{
{ ERROR_SUCCESS, ERRCODE_NONE },
{ ERROR_ACCESS_DENIED, SVSTREAM_ACCESS_DENIED },
{ ERROR_ACCOUNT_DISABLED, SVSTREAM_ACCESS_DENIED },
{ ERROR_ACCOUNT_EXPIRED, SVSTREAM_ACCESS_DENIED },
{ ERROR_ACCOUNT_RESTRICTION, SVSTREAM_ACCESS_DENIED },
{ ERROR_ATOMIC_LOCKS_NOT_SUPPORTED, SVSTREAM_INVALID_PARAMETER },
{ ERROR_BAD_PATHNAME, SVSTREAM_PATH_NOT_FOUND },
// Filename too long
{ ERROR_BUFFER_OVERFLOW, SVSTREAM_INVALID_PARAMETER },
{ ERROR_DIRECTORY, SVSTREAM_INVALID_PARAMETER },
{ ERROR_DRIVE_LOCKED, SVSTREAM_LOCKING_VIOLATION },
{ ERROR_FILE_NOT_FOUND, SVSTREAM_FILE_NOT_FOUND },
{ ERROR_FILENAME_EXCED_RANGE, SVSTREAM_INVALID_PARAMETER },
{ ERROR_INVALID_ACCESS, SVSTREAM_INVALID_ACCESS },
{ ERROR_INVALID_DRIVE, SVSTREAM_PATH_NOT_FOUND },
{ ERROR_INVALID_HANDLE, SVSTREAM_INVALID_HANDLE },
{ ERROR_INVALID_NAME, SVSTREAM_PATH_NOT_FOUND },
{ ERROR_INVALID_PARAMETER, SVSTREAM_INVALID_PARAMETER },
{ ERROR_IS_SUBST_PATH, SVSTREAM_INVALID_PARAMETER },
{ ERROR_IS_SUBST_TARGET, SVSTREAM_INVALID_PARAMETER },
{ ERROR_LOCK_FAILED, SVSTREAM_LOCKING_VIOLATION },
{ ERROR_LOCK_VIOLATION, SVSTREAM_LOCKING_VIOLATION },
{ ERROR_NEGATIVE_SEEK, SVSTREAM_SEEK_ERROR },
{ ERROR_PATH_NOT_FOUND, SVSTREAM_PATH_NOT_FOUND },
{ ERROR_READ_FAULT, SVSTREAM_READ_ERROR },
{ ERROR_SEEK, SVSTREAM_SEEK_ERROR },
{ ERROR_SEEK_ON_DEVICE, SVSTREAM_SEEK_ERROR },
{ ERROR_SHARING_BUFFER_EXCEEDED,SVSTREAM_SHARE_BUFF_EXCEEDED },
{ ERROR_SHARING_PAUSED, SVSTREAM_SHARING_VIOLATION },
{ ERROR_SHARING_VIOLATION, SVSTREAM_SHARING_VIOLATION },
{ ERROR_TOO_MANY_OPEN_FILES, SVSTREAM_TOO_MANY_OPEN_FILES },
{ ERROR_WRITE_FAULT, SVSTREAM_WRITE_ERROR },
{ ERROR_WRITE_PROTECT, SVSTREAM_ACCESS_DENIED },
{ ERROR_DISK_FULL, SVSTREAM_DISK_FULL },
{ DWORD(0 xFFFFFFFF), SVSTREAM_GENERALERROR }
};
ErrCode nRetVal = SVSTREAM_GENERALERROR; // default error
int i=0 ;
do
{
if ( errArr[i].wnt == nWntError )
{
nRetVal = errArr[i].sv;
break ;
}
i++;
} while ( errArr[i].wnt != DWORD(0 xFFFFFFFF) );
return nRetVal;
}
SvFileStream::SvFileStream( const OUString& rFileName, StreamMode nMode )
{
bIsOpen = false ;
nLockCounter = 0 ;
m_isWritable = false ;
SetBufferSize( 8192 );
// convert URL to SystemPath, if necessary
OUString aFileName;
if ( FileBase::getSystemPathFromFileURL( rFileName, aFileName ) != FileBase::E_None )
aFileName = rFileName;
Open( aFileName, nMode );
}
SvFileStream::SvFileStream()
{
bIsOpen = false ;
nLockCounter = 0 ;
m_isWritable = false ;
SetBufferSize( 8192 );
}
SvFileStream::~SvFileStream()
{
Close();
}
/// Does not check for EOF, makes isEof callable
std::size_t SvFileStream::GetData( void * pData, std::size_t nSize )
{
DWORD nCount = 0 ;
if ( IsOpen() )
{
bool bResult = ReadFile(mxFileHandle,pData,nSize,&nCount,nullptr);
if ( !bResult )
{
std::size_t nTestError = GetLastError();
SetError(::GetSvError( nTestError ) );
}
}
return nCount;
}
std::size_t SvFileStream::PutData( const void * pData, std::size_t nSize )
{
DWORD nCount = 0 ;
if ( IsOpen() )
{
if (!WriteFile(mxFileHandle,pData,nSize,&nCount,nullptr))
SetError(::GetSvError( GetLastError() ) );
}
return nCount;
}
sal_uInt64 SvFileStream::SeekPos(sal_uInt64 const nPos)
{
// check if a truncated STREAM_SEEK_TO_END was passed
assert(nPos != SAL_MAX_UINT32);
LARGE_INTEGER nNewPos, nActPos;
nNewPos.QuadPart = 0 ;
nActPos.QuadPart = nPos;
bool result = false ;
if ( IsOpen() )
{
if ( nPos != STREAM_SEEK_TO_END )
{
result = SetFilePointerEx(mxFileHandle, nActPos, &nNewPos, FILE_BEGIN);
}
else
{
result = SetFilePointerEx(mxFileHandle, nNewPos, &nNewPos, FILE_END);
}
if (!result)
{
SetError(::GetSvError(GetLastError()));
return 0 ;
}
}
else
SetError( SVSTREAM_GENERALERROR );
return static_cast <sal_uInt64>(nNewPos.QuadPart);
}
void SvFileStream::FlushData()
{
if ( IsOpen() )
{
if ( !FlushFileBuffers(mxFileHandle) )
SetError(::GetSvError(GetLastError()));
}
}
bool SvFileStream::LockFile()
{
bool bRetVal = false ;
if ( !nLockCounter )
{
if ( IsOpen() )
{
bRetVal = ::LockFile(mxFileHandle,0 L,0 L,LONG_MAX,0 L );
if ( bRetVal )
{
nLockCounter = 1 ;
}
else
SetError(::GetSvError(GetLastError()));
}
}
else
{
nLockCounter++;
bRetVal = true ;
}
return bRetVal;
}
void SvFileStream::UnlockFile()
{
if ( nLockCounter > 0 )
{
if ( nLockCounter == 1 )
{
if ( IsOpen() )
{
if ( ::UnlockFile(mxFileHandle,0 L,0 L,LONG_MAX,0 L ) )
{
nLockCounter = 0 ;
}
else
SetError(::GetSvError(GetLastError()));
}
}
else
{
nLockCounter--;
}
}
}
/*
NOCREATE TRUNC NT - Action
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0 ( Create ) 0 OPEN_ALWAYS
0 ( Create ) 1 CREATE_ALWAYS
1 0 OPEN_EXISTING
1 1 TRUNCATE_EXISTING
*/
void SvFileStream::Open( const OUString& rFilename, StreamMode nMode )
{
OUString aParsedFilename(rFilename);
SetLastError( ERROR_SUCCESS );
Close();
SvStream::ClearBuffer();
m_eStreamMode = nMode;
m_eStreamMode &= ~StreamMode::TRUNC; // don't truncate on reopen
aFilename = aParsedFilename;
SetLastError( ERROR_SUCCESS ); // might be changed by Redirector
DWORD nOpenAction;
DWORD nShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD nAccessMode = 0 ;
UINT nOldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX );
if ( nMode & StreamMode::SHARE_DENYREAD)
nShareMode &= ~FILE_SHARE_READ;
if ( nMode & StreamMode::SHARE_DENYWRITE)
nShareMode &= ~FILE_SHARE_WRITE;
if ( nMode & StreamMode::SHARE_DENYALL)
nShareMode = 0 ;
if ( nMode & StreamMode::READ )
nAccessMode |= GENERIC_READ;
if ( nMode & StreamMode::WRITE )
nAccessMode |= GENERIC_WRITE;
if ( nAccessMode == GENERIC_READ ) // ReadOnly ?
nMode |= StreamMode::NOCREATE; // Don't create if readonly
// Assignment based on true/false table above
if ( !(nMode & StreamMode::NOCREATE) )
{
if ( nMode & StreamMode::TRUNC )
nOpenAction = CREATE_ALWAYS;
else
nOpenAction = OPEN_ALWAYS;
}
else
{
if ( nMode & StreamMode::TRUNC )
nOpenAction = TRUNCATE_EXISTING;
else
nOpenAction = OPEN_EXISTING;
}
DWORD nAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS;
if ( nMode & StreamMode::TEMPORARY )
nAttributes |= FILE_ATTRIBUTE_TEMPORARY;
if ( nMode & StreamMode::DELETE_ON_CLOSE )
nAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
mxFileHandle = CreateFileW(
o3tl::toW(aFilename.getStr()),
nAccessMode,
nShareMode,
nullptr,
nOpenAction,
nAttributes,
nullptr
);
if ( mxFileHandle!=INVALID_HANDLE_VALUE && (
// Did Create Always overwrite a file?
GetLastError() == ERROR_ALREADY_EXISTS ||
// Did Create Always open a new file?
GetLastError() == ERROR_FILE_NOT_FOUND ))
{
// If so, no error
if ( nOpenAction == OPEN_ALWAYS || nOpenAction == CREATE_ALWAYS )
SetLastError( ERROR_SUCCESS );
}
// Otherwise, determine if we're allowed to read
if ( (mxFileHandle==INVALID_HANDLE_VALUE) &&
(nAccessMode & GENERIC_WRITE))
{
ErrCode nErr = ::GetSvError( GetLastError() );
if (nErr==SVSTREAM_ACCESS_DENIED || nErr==SVSTREAM_SHARING_VIOLATION)
{
nMode &= ~StreamMode::WRITE;
nAccessMode = GENERIC_READ;
// OV, 28.1.97: Win32 sets file to length 0
// if Openaction is CREATE_ALWAYS
nOpenAction = OPEN_EXISTING;
SetLastError( ERROR_SUCCESS );
mxFileHandle = CreateFileW(
o3tl::toW(aFilename.getStr()),
GENERIC_READ,
nShareMode,
nullptr,
nOpenAction,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
nullptr
);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
SetLastError( ERROR_SUCCESS );
}
}
if ( GetLastError() != ERROR_SUCCESS )
{
bIsOpen = false ;
SetError(::GetSvError( GetLastError() ) );
}
else
{
bIsOpen = true ;
// pInstanceData->bIsEof = false;
if ( nAccessMode & GENERIC_WRITE )
m_isWritable = true ;
}
SetErrorMode( nOldErrorMode );
}
void SvFileStream::Close()
{
if ( IsOpen() )
{
if ( nLockCounter )
{
nLockCounter = 1 ;
UnlockFile();
}
FlushBuffer();
CloseHandle( mxFileHandle );
}
bIsOpen = false ;
nLockCounter= 0 ;
m_isWritable = false ;
SvStream::ClearBuffer();
SvStream::ClearError();
}
/// Reset filepointer to beginning of file
void SvFileStream::ResetError()
{
SvStream::ClearError();
}
void SvFileStream::SetSize(sal_uInt64 const nSize)
{
if ( IsOpen() )
{
bool bError = false ;
HANDLE hFile = mxFileHandle;
DWORD const nOld = SetFilePointer( hFile, 0 L, nullptr, FILE_CURRENT );
if ( nOld != 0 xffffffff )
{
if ( SetFilePointer(hFile,nSize,nullptr,FILE_BEGIN ) != 0 xffffffff)
{
bool bSucc = SetEndOfFile( hFile );
if ( !bSucc )
bError = true ;
}
if ( SetFilePointer( hFile,nOld,nullptr,FILE_BEGIN ) == 0 xffffffff)
bError = true ;
}
if ( bError )
SetError(::GetSvError( GetLastError() ) );
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=94 H=97 G=95
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland