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 <tools/stream.hxx>
32 #include <osl/file.hxx>
46 static sal_uIntPtr
GetSvError( DWORD nWntError
)
48 static struct { DWORD wnt
; sal_uIntPtr sv
; } errArr
[] =
50 { ERROR_SUCCESS
, SVSTREAM_OK
},
51 { ERROR_ACCESS_DENIED
, SVSTREAM_ACCESS_DENIED
},
52 { ERROR_ACCOUNT_DISABLED
, SVSTREAM_ACCESS_DENIED
},
53 { ERROR_ACCOUNT_EXPIRED
, SVSTREAM_ACCESS_DENIED
},
54 { ERROR_ACCOUNT_RESTRICTION
, SVSTREAM_ACCESS_DENIED
},
55 { ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
, SVSTREAM_INVALID_PARAMETER
},
56 { ERROR_BAD_PATHNAME
, SVSTREAM_PATH_NOT_FOUND
},
58 { ERROR_BUFFER_OVERFLOW
, SVSTREAM_INVALID_PARAMETER
},
59 { ERROR_DIRECTORY
, SVSTREAM_INVALID_PARAMETER
},
60 { ERROR_DRIVE_LOCKED
, SVSTREAM_LOCKING_VIOLATION
},
61 { ERROR_FILE_NOT_FOUND
, SVSTREAM_FILE_NOT_FOUND
},
62 { ERROR_FILENAME_EXCED_RANGE
, SVSTREAM_INVALID_PARAMETER
},
63 { ERROR_INVALID_ACCESS
, SVSTREAM_INVALID_ACCESS
},
64 { ERROR_INVALID_DRIVE
, SVSTREAM_PATH_NOT_FOUND
},
65 { ERROR_INVALID_HANDLE
, SVSTREAM_INVALID_HANDLE
},
66 { ERROR_INVALID_NAME
, SVSTREAM_PATH_NOT_FOUND
},
67 { ERROR_INVALID_PARAMETER
, SVSTREAM_INVALID_PARAMETER
},
68 { ERROR_IS_SUBST_PATH
, SVSTREAM_INVALID_PARAMETER
},
69 { ERROR_IS_SUBST_TARGET
, SVSTREAM_INVALID_PARAMETER
},
70 { ERROR_LOCK_FAILED
, SVSTREAM_LOCKING_VIOLATION
},
71 { ERROR_LOCK_VIOLATION
, SVSTREAM_LOCKING_VIOLATION
},
72 { ERROR_NEGATIVE_SEEK
, SVSTREAM_SEEK_ERROR
},
73 { ERROR_PATH_NOT_FOUND
, SVSTREAM_PATH_NOT_FOUND
},
74 { ERROR_READ_FAULT
, SVSTREAM_READ_ERROR
},
75 { ERROR_SEEK
, SVSTREAM_SEEK_ERROR
},
76 { ERROR_SEEK_ON_DEVICE
, SVSTREAM_SEEK_ERROR
},
77 { ERROR_SHARING_BUFFER_EXCEEDED
,SVSTREAM_SHARE_BUFF_EXCEEDED
},
78 { ERROR_SHARING_PAUSED
, SVSTREAM_SHARING_VIOLATION
},
79 { ERROR_SHARING_VIOLATION
, SVSTREAM_SHARING_VIOLATION
},
80 { ERROR_TOO_MANY_OPEN_FILES
, SVSTREAM_TOO_MANY_OPEN_FILES
},
81 { ERROR_WRITE_FAULT
, SVSTREAM_WRITE_ERROR
},
82 { ERROR_WRITE_PROTECT
, SVSTREAM_ACCESS_DENIED
},
83 { ERROR_DISK_FULL
, SVSTREAM_DISK_FULL
},
85 { (DWORD
)0xFFFFFFFF, SVSTREAM_GENERALERROR
}
88 sal_uIntPtr nRetVal
= SVSTREAM_GENERALERROR
; // default error
92 if( errArr
[i
].wnt
== nWntError
)
94 nRetVal
= errArr
[i
].sv
;
98 } while( errArr
[i
].wnt
!= (DWORD
)0xFFFFFFFF );
102 SvFileStream::SvFileStream( const String
& rFileName
, StreamMode nMode
)
106 bIsWritable
= sal_False
;
107 pInstanceData
= new StreamData
;
109 SetBufferSize( 8192 );
110 // convert URL to SystemPath, if necessary
111 OUString aFileName
, aNormPath
;
113 if ( FileBase::getSystemPathFromFileURL( rFileName
, aFileName
) != FileBase::E_None
)
114 aFileName
= rFileName
;
115 Open( aFileName
, nMode
);
118 SvFileStream::SvFileStream()
122 bIsWritable
= sal_False
;
123 pInstanceData
= new StreamData
;
125 SetBufferSize( 8192 );
128 SvFileStream::~SvFileStream()
132 delete pInstanceData
;
135 sal_uInt16
SvFileStream::IsA() const
137 return ID_FILESTREAM
;
140 /// Does not check for EOF, makes isEof callable
141 sal_uIntPtr
SvFileStream::GetData( void* pData
, sal_uIntPtr nSize
)
146 bool bResult
= ReadFile(pInstanceData
->hFile
,(LPVOID
)pData
,nSize
,&nCount
,NULL
);
149 sal_uIntPtr nTestError
= GetLastError();
150 SetError(::GetSvError( nTestError
) );
153 return (DWORD
)nCount
;
156 sal_uIntPtr
SvFileStream::PutData( const void* pData
, sal_uIntPtr nSize
)
161 if(!WriteFile(pInstanceData
->hFile
,(LPVOID
)pData
,nSize
,&nCount
,NULL
))
162 SetError(::GetSvError( GetLastError() ) );
167 sal_uIntPtr
SvFileStream::SeekPos( sal_uIntPtr nPos
)
172 if( nPos
!= STREAM_SEEK_TO_END
)
173 // 64-Bit files are not supported
174 nNewPos
=SetFilePointer(pInstanceData
->hFile
,nPos
,NULL
,FILE_BEGIN
);
176 nNewPos
=SetFilePointer(pInstanceData
->hFile
,0L,NULL
,FILE_END
);
178 if( nNewPos
== 0xFFFFFFFF )
180 SetError(::GetSvError( GetLastError() ) );
185 SetError( SVSTREAM_GENERALERROR
);
186 return (sal_uIntPtr
)nNewPos
;
189 void SvFileStream::FlushData()
193 if( !FlushFileBuffers(pInstanceData
->hFile
) )
194 SetError(::GetSvError(GetLastError()));
198 sal_Bool
SvFileStream::LockRange( sal_uIntPtr nByteOffset
, sal_uIntPtr nBytes
)
200 bool bRetVal
= false;
203 bRetVal
= ::LockFile(pInstanceData
->hFile
,nByteOffset
,0L,nBytes
,0L );
205 SetError(::GetSvError(GetLastError()));
210 sal_Bool
SvFileStream::UnlockRange( sal_uIntPtr nByteOffset
, sal_uIntPtr nBytes
)
212 bool bRetVal
= false;
215 bRetVal
= ::UnlockFile(pInstanceData
->hFile
,nByteOffset
,0L,nBytes
,0L );
217 SetError(::GetSvError(GetLastError()));
222 sal_Bool
SvFileStream::LockFile()
224 sal_Bool bRetVal
= sal_False
;
227 if( LockRange( 0L, LONG_MAX
) )
241 sal_Bool
SvFileStream::UnlockFile()
243 sal_Bool bRetVal
= sal_False
;
244 if( nLockCounter
> 0)
246 if( nLockCounter
== 1)
248 if( UnlockRange( 0L, LONG_MAX
) )
264 NOCREATE TRUNC NT-Action
265 ----------------------------------------------
266 0 (Create) 0 OPEN_ALWAYS
267 0 (Create) 1 CREATE_ALWAYS
269 1 1 TRUNCATE_EXISTING
271 void SvFileStream::Open( const String
& rFilename
, StreamMode nMode
)
273 String
aParsedFilename(rFilename
);
275 SetLastError( ERROR_SUCCESS
);
277 SvStream::ClearBuffer();
280 eStreamMode
&= ~STREAM_TRUNC
; // don't truncate on reopen
282 aFilename
= aParsedFilename
;
283 OString
aFileNameA(OUStringToOString(aFilename
, osl_getThreadTextEncoding()));
284 SetLastError( ERROR_SUCCESS
); // might be changed by Redirector
287 DWORD nShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
288 DWORD nAccessMode
= 0L;
289 UINT nOldErrorMode
= SetErrorMode( SEM_FAILCRITICALERRORS
|SEM_NOOPENFILEERRORBOX
);
291 if( nMode
& STREAM_SHARE_DENYREAD
)
292 nShareMode
&= ~FILE_SHARE_READ
;
294 if( nMode
& STREAM_SHARE_DENYWRITE
)
295 nShareMode
&= ~FILE_SHARE_WRITE
;
297 if( nMode
& STREAM_SHARE_DENYALL
)
300 if( (nMode
& STREAM_READ
) )
301 nAccessMode
|= GENERIC_READ
;
302 if( (nMode
& STREAM_WRITE
) )
303 nAccessMode
|= GENERIC_WRITE
;
305 if( nAccessMode
== GENERIC_READ
) // ReadOnly ?
306 nMode
|= STREAM_NOCREATE
; // Don't create if readonly
308 // Assignment based on true/false table above
309 if( !(nMode
& STREAM_NOCREATE
) )
311 if( nMode
& STREAM_TRUNC
)
312 nOpenAction
= CREATE_ALWAYS
;
314 nOpenAction
= OPEN_ALWAYS
;
318 if( nMode
& STREAM_TRUNC
)
319 nOpenAction
= TRUNCATE_EXISTING
;
321 nOpenAction
= OPEN_EXISTING
;
324 pInstanceData
->hFile
= CreateFile(
328 (LPSECURITY_ATTRIBUTES
)NULL
,
330 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
334 if( pInstanceData
->hFile
!=INVALID_HANDLE_VALUE
&& (
335 // Did Create Always overwrite a file?
336 GetLastError() == ERROR_ALREADY_EXISTS
||
337 // Did Create Always open a new file?
338 GetLastError() == ERROR_FILE_NOT_FOUND
))
341 if( nOpenAction
== OPEN_ALWAYS
|| nOpenAction
== CREATE_ALWAYS
)
342 SetLastError( ERROR_SUCCESS
);
345 // Otherwise, determine if we're allowed to read
346 if( (pInstanceData
->hFile
==INVALID_HANDLE_VALUE
) &&
347 (nAccessMode
& GENERIC_WRITE
))
349 sal_uIntPtr nErr
= ::GetSvError( GetLastError() );
350 if(nErr
==SVSTREAM_ACCESS_DENIED
|| nErr
==SVSTREAM_SHARING_VIOLATION
)
352 nMode
&= (~STREAM_WRITE
);
353 nAccessMode
= GENERIC_READ
;
354 // OV, 28.1.97: Win32 sets file to length 0
355 // if Openaction is CREATE_ALWAYS
356 nOpenAction
= OPEN_EXISTING
;
357 SetLastError( ERROR_SUCCESS
);
358 pInstanceData
->hFile
= CreateFile(
362 (LPSECURITY_ATTRIBUTES
)NULL
,
364 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_RANDOM_ACCESS
,
367 if( GetLastError() == ERROR_ALREADY_EXISTS
)
368 SetLastError( ERROR_SUCCESS
);
372 if( GetLastError() != ERROR_SUCCESS
)
375 SetError(::GetSvError( GetLastError() ) );
380 // pInstanceData->bIsEof = sal_False;
381 if( nAccessMode
& GENERIC_WRITE
)
382 bIsWritable
= sal_True
;
384 SetErrorMode( nOldErrorMode
);
387 void SvFileStream::Close()
397 CloseHandle( pInstanceData
->hFile
);
401 bIsWritable
= sal_False
;
402 SvStream::ClearBuffer();
403 SvStream::ClearError();
406 /// Reset filepointer to beginning of file
407 void SvFileStream::ResetError()
409 SvStream::ClearError();
412 void SvFileStream::SetSize( sal_uIntPtr nSize
)
417 int bError
= sal_False
;
418 HANDLE hFile
= pInstanceData
->hFile
;
419 sal_uIntPtr nOld
= SetFilePointer( hFile
, 0L, NULL
, FILE_CURRENT
);
420 if( nOld
!= 0xffffffff )
422 if( SetFilePointer(hFile
,nSize
,NULL
,FILE_BEGIN
) != 0xffffffff)
424 bool bSucc
= SetEndOfFile( hFile
);
428 if( SetFilePointer( hFile
,nOld
,NULL
,FILE_BEGIN
) == 0xffffffff)
432 SetError(::GetSvError( GetLastError() ) );
436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */