summaryrefslogtreecommitdiffstats
path: root/tools/source/stream/strmwnt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'tools/source/stream/strmwnt.cxx')
-rw-r--r--tools/source/stream/strmwnt.cxx420
1 files changed, 420 insertions, 0 deletions
diff --git a/tools/source/stream/strmwnt.cxx b/tools/source/stream/strmwnt.cxx
new file mode 100644
index 000000000..4ea9c7eb1
--- /dev/null
+++ b/tools/source/stream/strmwnt.cxx
@@ -0,0 +1,420 @@
+/* -*- 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;
+
+class StreamData
+{
+public:
+ HANDLE hFile;
+
+ StreamData() : hFile(nullptr)
+ {
+ }
+};
+
+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(0xFFFFFFFF), 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(0xFFFFFFFF) );
+ return nRetVal;
+}
+
+SvFileStream::SvFileStream( const OUString& rFileName, StreamMode nMode )
+{
+ bIsOpen = false;
+ nLockCounter = 0;
+ m_isWritable = false;
+ pInstanceData.reset( new StreamData );
+
+ 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;
+ pInstanceData.reset( new StreamData );
+
+ 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(pInstanceData->hFile,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(pInstanceData->hFile,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);
+ DWORD nNewPos = 0;
+ if( IsOpen() )
+ {
+ if( nPos != STREAM_SEEK_TO_END )
+ // 64-Bit files are not supported
+ nNewPos=SetFilePointer(pInstanceData->hFile,nPos,nullptr,FILE_BEGIN);
+ else
+ nNewPos=SetFilePointer(pInstanceData->hFile,0L,nullptr,FILE_END);
+
+ if( nNewPos == 0xFFFFFFFF )
+ {
+ SetError(::GetSvError( GetLastError() ) );
+ nNewPos = 0;
+ }
+ }
+ else
+ SetError( SVSTREAM_GENERALERROR );
+ return static_cast<sal_uInt64>(nNewPos);
+}
+
+void SvFileStream::FlushData()
+{
+ if( IsOpen() )
+ {
+ if( !FlushFileBuffers(pInstanceData->hFile) )
+ SetError(::GetSvError(GetLastError()));
+ }
+}
+
+bool SvFileStream::LockFile()
+{
+ bool bRetVal = false;
+ if( !nLockCounter )
+ {
+ if( IsOpen() )
+ {
+ bRetVal = ::LockFile(pInstanceData->hFile,0L,0L,LONG_MAX,0L );
+ 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(pInstanceData->hFile,0L,0L,LONG_MAX,0L ) )
+ {
+ 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;
+
+ pInstanceData->hFile = CreateFileW(
+ o3tl::toW(aFilename.getStr()),
+ nAccessMode,
+ nShareMode,
+ nullptr,
+ nOpenAction,
+ nAttributes,
+ nullptr
+ );
+
+ if( pInstanceData->hFile!=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( (pInstanceData->hFile==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 );
+ pInstanceData->hFile = 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( pInstanceData->hFile );
+ }
+ 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 = pInstanceData->hFile;
+ DWORD const nOld = SetFilePointer( hFile, 0L, nullptr, FILE_CURRENT );
+ if( nOld != 0xffffffff )
+ {
+ if( SetFilePointer(hFile,nSize,nullptr,FILE_BEGIN ) != 0xffffffff)
+ {
+ bool bSucc = SetEndOfFile( hFile );
+ if( !bSucc )
+ bError = true;
+ }
+ if( SetFilePointer( hFile,nOld,nullptr,FILE_BEGIN ) == 0xffffffff)
+ bError = true;
+ }
+ if( bError )
+ SetError(::GetSvError( GetLastError() ) );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */