1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // TODO: StreamMode <-> AllocateMemory
26 #if !defined WIN32_LEAN_AND_MEAN
27 # define WIN32_LEAN_AND_MEAN
32 #include <osl/thread.h>
33 #include <tools/stream.hxx>
34 #include <o3tl/char16_t2wchar_t.hxx>
36 #include <osl/file.hxx>
39 static ErrCode
GetSvError( DWORD nWntError
)
41 static struct { DWORD wnt
; ErrCode sv
; } errArr
[] =
43 { ERROR_SUCCESS
, ERRCODE_NONE
},
44 { ERROR_ACCESS_DENIED
, SVSTREAM_ACCESS_DENIED
},
45 { ERROR_ACCOUNT_DISABLED
, SVSTREAM_ACCESS_DENIED
},
46 { ERROR_ACCOUNT_EXPIRED
, SVSTREAM_ACCESS_DENIED
},
47 { ERROR_ACCOUNT_RESTRICTION
, SVSTREAM_ACCESS_DENIED
},
48 { ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
, SVSTREAM_INVALID_PARAMETER
},
49 { ERROR_BAD_PATHNAME
, SVSTREAM_PATH_NOT_FOUND
},
51 { ERROR_BUFFER_OVERFLOW
, SVSTREAM_INVALID_PARAMETER
},
52 { ERROR_DIRECTORY
, SVSTREAM_INVALID_PARAMETER
},
53 { ERROR_DRIVE_LOCKED
, SVSTREAM_LOCKING_VIOLATION
},
54 { ERROR_FILE_NOT_FOUND
, SVSTREAM_FILE_NOT_FOUND
},
55 { ERROR_FILENAME_EXCED_RANGE
, SVSTREAM_INVALID_PARAMETER
},
56 { ERROR_INVALID_ACCESS
, SVSTREAM_INVALID_ACCESS
},
57 { ERROR_INVALID_DRIVE
, SVSTREAM_PATH_NOT_FOUND
},
58 { ERROR_INVALID_HANDLE
, SVSTREAM_INVALID_HANDLE
},
59 { ERROR_INVALID_NAME
, SVSTREAM_PATH_NOT_FOUND
},
60 { ERROR_INVALID_PARAMETER
, SVSTREAM_INVALID_PARAMETER
},
61 { ERROR_IS_SUBST_PATH
, SVSTREAM_INVALID_PARAMETER
},
62 { ERROR_IS_SUBST_TARGET
, SVSTREAM_INVALID_PARAMETER
},
63 { ERROR_LOCK_FAILED
, SVSTREAM_LOCKING_VIOLATION
},
64 { ERROR_LOCK_VIOLATION
, SVSTREAM_LOCKING_VIOLATION
},
65 { ERROR_NEGATIVE_SEEK
, SVSTREAM_SEEK_ERROR
},
66 { ERROR_PATH_NOT_FOUND
, SVSTREAM_PATH_NOT_FOUND
},
67 { ERROR_READ_FAULT
, SVSTREAM_READ_ERROR
},
68 { ERROR_SEEK
, SVSTREAM_SEEK_ERROR
},
69 { ERROR_SEEK_ON_DEVICE
, SVSTREAM_SEEK_ERROR
},
70 { ERROR_SHARING_BUFFER_EXCEEDED
,SVSTREAM_SHARE_BUFF_EXCEEDED
},
71 { ERROR_SHARING_PAUSED
, SVSTREAM_SHARING_VIOLATION
},
72 { ERROR_SHARING_VIOLATION
, SVSTREAM_SHARING_VIOLATION
},
73 { ERROR_TOO_MANY_OPEN_FILES
, SVSTREAM_TOO_MANY_OPEN_FILES
},
74 { ERROR_WRITE_FAULT
, SVSTREAM_WRITE_ERROR
},
75 { ERROR_WRITE_PROTECT
, SVSTREAM_ACCESS_DENIED
},
76 { ERROR_DISK_FULL
, SVSTREAM_DISK_FULL
},
78 { DWORD(0xFFFFFFFF), SVSTREAM_GENERALERROR
}
81 ErrCode nRetVal
= SVSTREAM_GENERALERROR
; // default error
85 if( errArr
[i
].wnt
== nWntError
)
87 nRetVal
= errArr
[i
].sv
;
91 } while( errArr
[i
].wnt
!= DWORD(0xFFFFFFFF) );
95 SvFileStream::SvFileStream( const OUString
& rFileName
, StreamMode nMode
)
101 SetBufferSize( 8192 );
102 // convert URL to SystemPath, if necessary
105 if ( FileBase::getSystemPathFromFileURL( rFileName
, aFileName
) != FileBase::E_None
)
106 aFileName
= rFileName
;
107 Open( aFileName
, nMode
);
110 SvFileStream::SvFileStream()
114 m_isWritable
= false;
116 SetBufferSize( 8192 );
119 SvFileStream::~SvFileStream()
124 /// Does not check for EOF, makes isEof callable
125 std::size_t SvFileStream::GetData( void* pData
, std::size_t nSize
)
130 bool bResult
= ReadFile(mxFileHandle
,pData
,nSize
,&nCount
,nullptr);
133 std::size_t nTestError
= GetLastError();
134 SetError(::GetSvError( nTestError
) );
140 std::size_t SvFileStream::PutData( const void* pData
, std::size_t nSize
)
145 if(!WriteFile(mxFileHandle
,pData
,nSize
,&nCount
,nullptr))
146 SetError(::GetSvError( GetLastError() ) );
151 sal_uInt64
SvFileStream::SeekPos(sal_uInt64
const nPos
)
153 // check if a truncated STREAM_SEEK_TO_END was passed
154 assert(nPos
!= SAL_MAX_UINT32
);
155 LARGE_INTEGER nNewPos
, nActPos
;
156 nNewPos
.QuadPart
= 0;
157 nActPos
.QuadPart
= nPos
;
161 if( nPos
!= STREAM_SEEK_TO_END
)
163 result
= SetFilePointerEx(mxFileHandle
, nActPos
, &nNewPos
, FILE_BEGIN
);
167 result
= SetFilePointerEx(mxFileHandle
, nNewPos
, &nNewPos
, FILE_END
);
171 SetError(::GetSvError(GetLastError()));
176 SetError( SVSTREAM_GENERALERROR
);
177 return static_cast<sal_uInt64
>(nNewPos
.QuadPart
);
180 void SvFileStream::FlushData()
184 if( !FlushFileBuffers(mxFileHandle
) )
185 SetError(::GetSvError(GetLastError()));
189 bool SvFileStream::LockFile()
191 bool bRetVal
= false;
196 bRetVal
= ::LockFile(mxFileHandle
,0L,0L,LONG_MAX
,0L );
202 SetError(::GetSvError(GetLastError()));
213 void SvFileStream::UnlockFile()
215 if( nLockCounter
> 0)
217 if( nLockCounter
== 1)
221 if( ::UnlockFile(mxFileHandle
,0L,0L,LONG_MAX
,0L ) )
226 SetError(::GetSvError(GetLastError()));
237 NOCREATE TRUNC NT-Action
238 ----------------------------------------------
239 0 (Create) 0 OPEN_ALWAYS
240 0 (Create) 1 CREATE_ALWAYS
242 1 1 TRUNCATE_EXISTING
244 void SvFileStream::Open( const OUString
& rFilename
, StreamMode nMode
)
246 OUString
aParsedFilename(rFilename
);
248 SetLastError( ERROR_SUCCESS
);
250 SvStream::ClearBuffer();
252 m_eStreamMode
= nMode
;
253 m_eStreamMode
&= ~StreamMode::TRUNC
; // don't truncate on reopen
255 aFilename
= aParsedFilename
;
256 SetLastError( ERROR_SUCCESS
); // might be changed by Redirector
259 DWORD nShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
260 DWORD nAccessMode
= 0;
261 UINT nOldErrorMode
= SetErrorMode( SEM_FAILCRITICALERRORS
|SEM_NOOPENFILEERRORBOX
);
263 if( nMode
& StreamMode::SHARE_DENYREAD
)
264 nShareMode
&= ~FILE_SHARE_READ
;
266 if( nMode
& StreamMode::SHARE_DENYWRITE
)
267 nShareMode
&= ~FILE_SHARE_WRITE
;
269 if( nMode
& StreamMode::SHARE_DENYALL
)
272 if( nMode
& StreamMode::READ
)
273 nAccessMode
|= GENERIC_READ
;
274 if( nMode
& StreamMode::WRITE
)
275 nAccessMode
|= GENERIC_WRITE
;
277 if( nAccessMode
== GENERIC_READ
) // ReadOnly ?
278 nMode
|= StreamMode::NOCREATE
; // Don't create if readonly
280 // Assignment based on true/false table above
281 if( !(nMode
& StreamMode::NOCREATE
) )
283 if( nMode
& StreamMode::TRUNC
)
284 nOpenAction
= CREATE_ALWAYS
;
286 nOpenAction
= OPEN_ALWAYS
;
290 if( nMode
& StreamMode::TRUNC
)
291 nOpenAction
= TRUNCATE_EXISTING
;
293 nOpenAction
= OPEN_EXISTING
;
296 DWORD nAttributes
= FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
;
298 if ( nMode
& StreamMode::TEMPORARY
)
299 nAttributes
|= FILE_ATTRIBUTE_TEMPORARY
;
300 if ( nMode
& StreamMode::DELETE_ON_CLOSE
)
301 nAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
303 mxFileHandle
= CreateFileW(
304 o3tl::toW(aFilename
.getStr()),
313 if( mxFileHandle
!=INVALID_HANDLE_VALUE
&& (
314 // Did Create Always overwrite a file?
315 GetLastError() == ERROR_ALREADY_EXISTS
||
316 // Did Create Always open a new file?
317 GetLastError() == ERROR_FILE_NOT_FOUND
))
320 if( nOpenAction
== OPEN_ALWAYS
|| nOpenAction
== CREATE_ALWAYS
)
321 SetLastError( ERROR_SUCCESS
);
324 // Otherwise, determine if we're allowed to read
325 if( (mxFileHandle
==INVALID_HANDLE_VALUE
) &&
326 (nAccessMode
& GENERIC_WRITE
))
328 ErrCode nErr
= ::GetSvError( GetLastError() );
329 if(nErr
==SVSTREAM_ACCESS_DENIED
|| nErr
==SVSTREAM_SHARING_VIOLATION
)
331 nMode
&= ~StreamMode::WRITE
;
332 nAccessMode
= GENERIC_READ
;
333 // OV, 28.1.97: Win32 sets file to length 0
334 // if Openaction is CREATE_ALWAYS
335 nOpenAction
= OPEN_EXISTING
;
336 SetLastError( ERROR_SUCCESS
);
337 mxFileHandle
= CreateFileW(
338 o3tl::toW(aFilename
.getStr()),
343 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
346 if( GetLastError() == ERROR_ALREADY_EXISTS
)
347 SetLastError( ERROR_SUCCESS
);
351 if( GetLastError() != ERROR_SUCCESS
)
354 SetError(::GetSvError( GetLastError() ) );
359 // pInstanceData->bIsEof = false;
360 if( nAccessMode
& GENERIC_WRITE
)
363 SetErrorMode( nOldErrorMode
);
366 void SvFileStream::Close()
376 CloseHandle( mxFileHandle
);
380 m_isWritable
= false;
381 SvStream::ClearBuffer();
382 SvStream::ClearError();
385 /// Reset filepointer to beginning of file
386 void SvFileStream::ResetError()
388 SvStream::ClearError();
391 void SvFileStream::SetSize(sal_uInt64
const nSize
)
397 HANDLE hFile
= mxFileHandle
;
398 DWORD
const nOld
= SetFilePointer( hFile
, 0L, nullptr, FILE_CURRENT
);
399 if( nOld
!= 0xffffffff )
401 if( SetFilePointer(hFile
,nSize
,nullptr,FILE_BEGIN
) != 0xffffffff)
403 bool bSucc
= SetEndOfFile( hFile
);
407 if( SetFilePointer( hFile
,nOld
,nullptr,FILE_BEGIN
) == 0xffffffff)
411 SetError(::GetSvError( GetLastError() ) );
415 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */