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
29 #include <osl/thread.h>
30 #include <tools/stream.hxx>
33 #include <osl/file.hxx>
47 static sal_Size
GetSvError( DWORD nWntError
)
49 static struct { DWORD wnt
; sal_Size sv
; } errArr
[] =
51 { ERROR_SUCCESS
, SVSTREAM_OK
},
52 { ERROR_ACCESS_DENIED
, SVSTREAM_ACCESS_DENIED
},
53 { ERROR_ACCOUNT_DISABLED
, SVSTREAM_ACCESS_DENIED
},
54 { ERROR_ACCOUNT_EXPIRED
, SVSTREAM_ACCESS_DENIED
},
55 { ERROR_ACCOUNT_RESTRICTION
, SVSTREAM_ACCESS_DENIED
},
56 { ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
, SVSTREAM_INVALID_PARAMETER
},
57 { ERROR_BAD_PATHNAME
, SVSTREAM_PATH_NOT_FOUND
},
59 { ERROR_BUFFER_OVERFLOW
, SVSTREAM_INVALID_PARAMETER
},
60 { ERROR_DIRECTORY
, SVSTREAM_INVALID_PARAMETER
},
61 { ERROR_DRIVE_LOCKED
, SVSTREAM_LOCKING_VIOLATION
},
62 { ERROR_FILE_NOT_FOUND
, SVSTREAM_FILE_NOT_FOUND
},
63 { ERROR_FILENAME_EXCED_RANGE
, SVSTREAM_INVALID_PARAMETER
},
64 { ERROR_INVALID_ACCESS
, SVSTREAM_INVALID_ACCESS
},
65 { ERROR_INVALID_DRIVE
, SVSTREAM_PATH_NOT_FOUND
},
66 { ERROR_INVALID_HANDLE
, SVSTREAM_INVALID_HANDLE
},
67 { ERROR_INVALID_NAME
, SVSTREAM_PATH_NOT_FOUND
},
68 { ERROR_INVALID_PARAMETER
, SVSTREAM_INVALID_PARAMETER
},
69 { ERROR_IS_SUBST_PATH
, SVSTREAM_INVALID_PARAMETER
},
70 { ERROR_IS_SUBST_TARGET
, SVSTREAM_INVALID_PARAMETER
},
71 { ERROR_LOCK_FAILED
, SVSTREAM_LOCKING_VIOLATION
},
72 { ERROR_LOCK_VIOLATION
, SVSTREAM_LOCKING_VIOLATION
},
73 { ERROR_NEGATIVE_SEEK
, SVSTREAM_SEEK_ERROR
},
74 { ERROR_PATH_NOT_FOUND
, SVSTREAM_PATH_NOT_FOUND
},
75 { ERROR_READ_FAULT
, SVSTREAM_READ_ERROR
},
76 { ERROR_SEEK
, SVSTREAM_SEEK_ERROR
},
77 { ERROR_SEEK_ON_DEVICE
, SVSTREAM_SEEK_ERROR
},
78 { ERROR_SHARING_BUFFER_EXCEEDED
,SVSTREAM_SHARE_BUFF_EXCEEDED
},
79 { ERROR_SHARING_PAUSED
, SVSTREAM_SHARING_VIOLATION
},
80 { ERROR_SHARING_VIOLATION
, SVSTREAM_SHARING_VIOLATION
},
81 { ERROR_TOO_MANY_OPEN_FILES
, SVSTREAM_TOO_MANY_OPEN_FILES
},
82 { ERROR_WRITE_FAULT
, SVSTREAM_WRITE_ERROR
},
83 { ERROR_WRITE_PROTECT
, SVSTREAM_ACCESS_DENIED
},
84 { ERROR_DISK_FULL
, SVSTREAM_DISK_FULL
},
86 { (DWORD
)0xFFFFFFFF, SVSTREAM_GENERALERROR
}
89 sal_Size nRetVal
= SVSTREAM_GENERALERROR
; // default error
93 if( errArr
[i
].wnt
== nWntError
)
95 nRetVal
= errArr
[i
].sv
;
99 } while( errArr
[i
].wnt
!= (DWORD
)0xFFFFFFFF );
103 SvFileStream::SvFileStream( const OUString
& rFileName
, StreamMode nMode
)
108 pInstanceData
= new StreamData
;
110 SetBufferSize( 8192 );
111 // convert URL to SystemPath, if necessary
112 OUString aFileName
, aNormPath
;
114 if ( FileBase::getSystemPathFromFileURL( rFileName
, aFileName
) != FileBase::E_None
)
115 aFileName
= rFileName
;
116 Open( aFileName
, nMode
);
119 SvFileStream::SvFileStream()
124 pInstanceData
= new StreamData
;
126 SetBufferSize( 8192 );
129 SvFileStream::~SvFileStream()
133 delete pInstanceData
;
136 /// Does not check for EOF, makes isEof callable
137 sal_Size
SvFileStream::GetData( void* pData
, sal_Size nSize
)
142 bool bResult
= ReadFile(pInstanceData
->hFile
,(LPVOID
)pData
,nSize
,&nCount
,NULL
);
145 sal_Size nTestError
= GetLastError();
146 SetError(::GetSvError( nTestError
) );
149 return (DWORD
)nCount
;
152 sal_Size
SvFileStream::PutData( const void* pData
, sal_Size nSize
)
157 if(!WriteFile(pInstanceData
->hFile
,(LPVOID
)pData
,nSize
,&nCount
,NULL
))
158 SetError(::GetSvError( GetLastError() ) );
163 sal_uInt64
SvFileStream::SeekPos(sal_uInt64
const nPos
)
165 // check if a truncated STREAM_SEEK_TO_END was passed
166 assert(nPos
!= SAL_MAX_UINT32
);
170 if( nPos
!= STREAM_SEEK_TO_END
)
171 // 64-Bit files are not supported
172 nNewPos
=SetFilePointer(pInstanceData
->hFile
,nPos
,NULL
,FILE_BEGIN
);
174 nNewPos
=SetFilePointer(pInstanceData
->hFile
,0L,NULL
,FILE_END
);
176 if( nNewPos
== 0xFFFFFFFF )
178 SetError(::GetSvError( GetLastError() ) );
183 SetError( SVSTREAM_GENERALERROR
);
184 return static_cast<sal_uInt64
>(nNewPos
);
187 void SvFileStream::FlushData()
191 if( !FlushFileBuffers(pInstanceData
->hFile
) )
192 SetError(::GetSvError(GetLastError()));
196 bool SvFileStream::LockRange( sal_Size nByteOffset
, sal_Size nBytes
)
198 bool bRetVal
= false;
201 bRetVal
= ::LockFile(pInstanceData
->hFile
,nByteOffset
,0L,nBytes
,0L );
203 SetError(::GetSvError(GetLastError()));
208 bool SvFileStream::UnlockRange( sal_Size nByteOffset
, sal_Size nBytes
)
210 bool bRetVal
= false;
213 bRetVal
= ::UnlockFile(pInstanceData
->hFile
,nByteOffset
,0L,nBytes
,0L );
215 SetError(::GetSvError(GetLastError()));
220 bool SvFileStream::LockFile()
222 bool bRetVal
= false;
225 if( LockRange( 0L, LONG_MAX
) )
239 bool SvFileStream::UnlockFile()
241 bool bRetVal
= false;
242 if( nLockCounter
> 0)
244 if( nLockCounter
== 1)
246 if( UnlockRange( 0L, LONG_MAX
) )
262 NOCREATE TRUNC NT-Action
263 ----------------------------------------------
264 0 (Create) 0 OPEN_ALWAYS
265 0 (Create) 1 CREATE_ALWAYS
267 1 1 TRUNCATE_EXISTING
269 void SvFileStream::Open( const OUString
& rFilename
, StreamMode nMode
)
271 OUString
aParsedFilename(rFilename
);
273 SetLastError( ERROR_SUCCESS
);
275 SvStream::ClearBuffer();
278 eStreamMode
&= ~StreamMode::TRUNC
; // don't truncate on reopen
280 aFilename
= aParsedFilename
;
281 OString
aFileNameA(OUStringToOString(aFilename
, osl_getThreadTextEncoding()));
282 SetLastError( ERROR_SUCCESS
); // might be changed by Redirector
285 DWORD nShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
286 DWORD nAccessMode
= 0L;
287 UINT nOldErrorMode
= SetErrorMode( SEM_FAILCRITICALERRORS
|SEM_NOOPENFILEERRORBOX
);
289 if( nMode
& StreamMode::SHARE_DENYREAD
)
290 nShareMode
&= ~FILE_SHARE_READ
;
292 if( nMode
& StreamMode::SHARE_DENYWRITE
)
293 nShareMode
&= ~FILE_SHARE_WRITE
;
295 if( nMode
& StreamMode::SHARE_DENYALL
)
298 if( (nMode
& StreamMode::READ
) )
299 nAccessMode
|= GENERIC_READ
;
300 if( (nMode
& StreamMode::WRITE
) )
301 nAccessMode
|= GENERIC_WRITE
;
303 if( nAccessMode
== GENERIC_READ
) // ReadOnly ?
304 nMode
|= StreamMode::NOCREATE
; // Don't create if readonly
306 // Assignment based on true/false table above
307 if( !(nMode
& StreamMode::NOCREATE
) )
309 if( nMode
& StreamMode::TRUNC
)
310 nOpenAction
= CREATE_ALWAYS
;
312 nOpenAction
= OPEN_ALWAYS
;
316 if( nMode
& StreamMode::TRUNC
)
317 nOpenAction
= TRUNCATE_EXISTING
;
319 nOpenAction
= OPEN_EXISTING
;
322 pInstanceData
->hFile
= CreateFile(
326 (LPSECURITY_ATTRIBUTES
)NULL
,
328 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
332 if( pInstanceData
->hFile
!=INVALID_HANDLE_VALUE
&& (
333 // Did Create Always overwrite a file?
334 GetLastError() == ERROR_ALREADY_EXISTS
||
335 // Did Create Always open a new file?
336 GetLastError() == ERROR_FILE_NOT_FOUND
))
339 if( nOpenAction
== OPEN_ALWAYS
|| nOpenAction
== CREATE_ALWAYS
)
340 SetLastError( ERROR_SUCCESS
);
343 // Otherwise, determine if we're allowed to read
344 if( (pInstanceData
->hFile
==INVALID_HANDLE_VALUE
) &&
345 (nAccessMode
& GENERIC_WRITE
))
347 sal_Size nErr
= ::GetSvError( GetLastError() );
348 if(nErr
==SVSTREAM_ACCESS_DENIED
|| nErr
==SVSTREAM_SHARING_VIOLATION
)
350 nMode
&= (~StreamMode::WRITE
);
351 nAccessMode
= GENERIC_READ
;
352 // OV, 28.1.97: Win32 sets file to length 0
353 // if Openaction is CREATE_ALWAYS
354 nOpenAction
= OPEN_EXISTING
;
355 SetLastError( ERROR_SUCCESS
);
356 pInstanceData
->hFile
= CreateFile(
360 (LPSECURITY_ATTRIBUTES
)NULL
,
362 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
365 if( GetLastError() == ERROR_ALREADY_EXISTS
)
366 SetLastError( ERROR_SUCCESS
);
370 if( GetLastError() != ERROR_SUCCESS
)
373 SetError(::GetSvError( GetLastError() ) );
378 // pInstanceData->bIsEof = false;
379 if( nAccessMode
& GENERIC_WRITE
)
382 SetErrorMode( nOldErrorMode
);
385 void SvFileStream::Close()
395 CloseHandle( pInstanceData
->hFile
);
400 SvStream::ClearBuffer();
401 SvStream::ClearError();
404 /// Reset filepointer to beginning of file
405 void SvFileStream::ResetError()
407 SvStream::ClearError();
410 void SvFileStream::SetSize(sal_uInt64
const nSize
)
416 HANDLE hFile
= pInstanceData
->hFile
;
417 sal_Size nOld
= SetFilePointer( hFile
, 0L, NULL
, FILE_CURRENT
);
418 if( nOld
!= 0xffffffff )
420 if( SetFilePointer(hFile
,nSize
,NULL
,FILE_BEGIN
) != 0xffffffff)
422 bool bSucc
= SetEndOfFile( hFile
);
426 if( SetFilePointer( hFile
,nOld
,NULL
,FILE_BEGIN
) == 0xffffffff)
430 SetError(::GetSvError( GetLastError() ) );
434 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */