bump product version to 7.6.3.2-android
[LibreOffice.git] / tools / source / stream / strmwnt.cxx
blobd7d3a73ed2ce8b7699ccce799a463d7fa799b2e1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
22 #include <string.h>
23 #include <limits.h>
25 #ifdef _WIN32
26 #if !defined WIN32_LEAN_AND_MEAN
27 # define WIN32_LEAN_AND_MEAN
28 #endif
29 #include <windows.h>
30 #endif
32 #include <osl/thread.h>
33 #include <tools/stream.hxx>
34 #include <o3tl/char16_t2wchar_t.hxx>
36 #include <osl/file.hxx>
37 using namespace osl;
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 },
50 // Filename too long
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
82 int i=0;
85 if( errArr[i].wnt == nWntError )
87 nRetVal = errArr[i].sv;
88 break;
90 i++;
91 } while( errArr[i].wnt != DWORD(0xFFFFFFFF) );
92 return nRetVal;
95 SvFileStream::SvFileStream( const OUString& rFileName, StreamMode nMode )
97 bIsOpen = false;
98 nLockCounter = 0;
99 m_isWritable = false;
101 SetBufferSize( 8192 );
102 // convert URL to SystemPath, if necessary
103 OUString aFileName;
105 if ( FileBase::getSystemPathFromFileURL( rFileName, aFileName ) != FileBase::E_None )
106 aFileName = rFileName;
107 Open( aFileName, nMode );
110 SvFileStream::SvFileStream()
112 bIsOpen = false;
113 nLockCounter = 0;
114 m_isWritable = false;
116 SetBufferSize( 8192 );
119 SvFileStream::~SvFileStream()
121 Close();
124 /// Does not check for EOF, makes isEof callable
125 std::size_t SvFileStream::GetData( void* pData, std::size_t nSize )
127 DWORD nCount = 0;
128 if( IsOpen() )
130 bool bResult = ReadFile(mxFileHandle,pData,nSize,&nCount,nullptr);
131 if( !bResult )
133 std::size_t nTestError = GetLastError();
134 SetError(::GetSvError( nTestError ) );
137 return nCount;
140 std::size_t SvFileStream::PutData( const void* pData, std::size_t nSize )
142 DWORD nCount = 0;
143 if( IsOpen() )
145 if(!WriteFile(mxFileHandle,pData,nSize,&nCount,nullptr))
146 SetError(::GetSvError( GetLastError() ) );
148 return nCount;
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;
158 bool result = false;
159 if( IsOpen() )
161 if( nPos != STREAM_SEEK_TO_END )
163 result = SetFilePointerEx(mxFileHandle, nActPos, &nNewPos, FILE_BEGIN);
165 else
167 result = SetFilePointerEx(mxFileHandle, nNewPos, &nNewPos, FILE_END);
169 if (!result)
171 SetError(::GetSvError(GetLastError()));
172 return 0;
175 else
176 SetError( SVSTREAM_GENERALERROR );
177 return static_cast<sal_uInt64>(nNewPos.QuadPart);
180 void SvFileStream::FlushData()
182 if( IsOpen() )
184 if( !FlushFileBuffers(mxFileHandle) )
185 SetError(::GetSvError(GetLastError()));
189 bool SvFileStream::LockFile()
191 bool bRetVal = false;
192 if( !nLockCounter )
194 if( IsOpen() )
196 bRetVal = ::LockFile(mxFileHandle,0L,0L,LONG_MAX,0L );
197 if( bRetVal )
199 nLockCounter = 1;
201 else
202 SetError(::GetSvError(GetLastError()));
205 else
207 nLockCounter++;
208 bRetVal = true;
210 return bRetVal;
213 void SvFileStream::UnlockFile()
215 if( nLockCounter > 0)
217 if( nLockCounter == 1)
219 if( IsOpen() )
221 if( ::UnlockFile(mxFileHandle,0L,0L,LONG_MAX,0L ) )
223 nLockCounter = 0;
225 else
226 SetError(::GetSvError(GetLastError()));
229 else
231 nLockCounter--;
237 NOCREATE TRUNC NT-Action
238 ----------------------------------------------
239 0 (Create) 0 OPEN_ALWAYS
240 0 (Create) 1 CREATE_ALWAYS
241 1 0 OPEN_EXISTING
242 1 1 TRUNCATE_EXISTING
244 void SvFileStream::Open( const OUString& rFilename, StreamMode nMode )
246 OUString aParsedFilename(rFilename);
248 SetLastError( ERROR_SUCCESS );
249 Close();
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
258 DWORD nOpenAction;
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)
270 nShareMode = 0;
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;
285 else
286 nOpenAction = OPEN_ALWAYS;
288 else
290 if( nMode & StreamMode::TRUNC )
291 nOpenAction = TRUNCATE_EXISTING;
292 else
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()),
305 nAccessMode,
306 nShareMode,
307 nullptr,
308 nOpenAction,
309 nAttributes,
310 nullptr
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 ))
319 // If so, no error
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()),
339 GENERIC_READ,
340 nShareMode,
341 nullptr,
342 nOpenAction,
343 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
344 nullptr
346 if( GetLastError() == ERROR_ALREADY_EXISTS )
347 SetLastError( ERROR_SUCCESS );
351 if( GetLastError() != ERROR_SUCCESS )
353 bIsOpen = false;
354 SetError(::GetSvError( GetLastError() ) );
356 else
358 bIsOpen = true;
359 // pInstanceData->bIsEof = false;
360 if( nAccessMode & GENERIC_WRITE )
361 m_isWritable = true;
363 SetErrorMode( nOldErrorMode );
366 void SvFileStream::Close()
368 if( IsOpen() )
370 if( nLockCounter )
372 nLockCounter = 1;
373 UnlockFile();
375 FlushBuffer();
376 CloseHandle( mxFileHandle );
378 bIsOpen = false;
379 nLockCounter= 0;
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)
394 if( IsOpen() )
396 bool bError = false;
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 );
404 if( !bSucc )
405 bError = true;
407 if( SetFilePointer( hFile,nOld,nullptr,FILE_BEGIN ) == 0xffffffff)
408 bError = true;
410 if( bError )
411 SetError(::GetSvError( GetLastError() ) );
415 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */