1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // no include "precompiled_tools.hxx" because this file is included in strmsys.cxx
25
26 /*
27 Todo: StreamMode <-> AllocateMemory
28 */
29
30 #include <string.h>
31 #include <limits.h>
32
33 #include <tools/svwin.h>
34
35 #include <tools/debug.hxx>
36 #include <tools/fsys.hxx>
37 #include <tools/stream.hxx>
38
39 // class FileBase
40 #include <osl/file.hxx>
41 using namespace osl;
42
43 // -----------------------------------------------------------------------
44
45 // --------------
46 // - StreamData -
47 // --------------
48
49 class StreamData
50 {
51 public:
52 HANDLE hFile;
53
StreamData()54 StreamData()
55 {
56 hFile = 0;
57 }
58 };
59
60 // -----------------------------------------------------------------------
61
GetSvError(DWORD nWntError)62 static sal_uIntPtr GetSvError( DWORD nWntError )
63 {
64 static struct { DWORD wnt; sal_uIntPtr sv; } errArr[] =
65 {
66 { ERROR_SUCCESS, SVSTREAM_OK },
67 { ERROR_ACCESS_DENIED, SVSTREAM_ACCESS_DENIED },
68 { ERROR_ACCOUNT_DISABLED, SVSTREAM_ACCESS_DENIED },
69 { ERROR_ACCOUNT_EXPIRED, SVSTREAM_ACCESS_DENIED },
70 { ERROR_ACCOUNT_RESTRICTION, SVSTREAM_ACCESS_DENIED },
71 { ERROR_ATOMIC_LOCKS_NOT_SUPPORTED, SVSTREAM_INVALID_PARAMETER },
72 { ERROR_BAD_PATHNAME, SVSTREAM_PATH_NOT_FOUND },
73 // Filename too long
74 { ERROR_BUFFER_OVERFLOW, SVSTREAM_INVALID_PARAMETER },
75 { ERROR_DIRECTORY, SVSTREAM_INVALID_PARAMETER },
76 { ERROR_DRIVE_LOCKED, SVSTREAM_LOCKING_VIOLATION },
77 { ERROR_FILE_NOT_FOUND, SVSTREAM_FILE_NOT_FOUND },
78 { ERROR_FILENAME_EXCED_RANGE, SVSTREAM_INVALID_PARAMETER },
79 { ERROR_INVALID_ACCESS, SVSTREAM_INVALID_ACCESS },
80 { ERROR_INVALID_DRIVE, SVSTREAM_PATH_NOT_FOUND },
81 { ERROR_INVALID_HANDLE, SVSTREAM_INVALID_HANDLE },
82 { ERROR_INVALID_NAME, SVSTREAM_PATH_NOT_FOUND },
83 { ERROR_INVALID_PARAMETER, SVSTREAM_INVALID_PARAMETER },
84 { ERROR_IS_SUBST_PATH, SVSTREAM_INVALID_PARAMETER },
85 { ERROR_IS_SUBST_TARGET, SVSTREAM_INVALID_PARAMETER },
86 { ERROR_LOCK_FAILED, SVSTREAM_LOCKING_VIOLATION },
87 { ERROR_LOCK_VIOLATION, SVSTREAM_LOCKING_VIOLATION },
88 { ERROR_NEGATIVE_SEEK, SVSTREAM_SEEK_ERROR },
89 { ERROR_PATH_NOT_FOUND, SVSTREAM_PATH_NOT_FOUND },
90 { ERROR_READ_FAULT, SVSTREAM_READ_ERROR },
91 { ERROR_SEEK, SVSTREAM_SEEK_ERROR },
92 { ERROR_SEEK_ON_DEVICE, SVSTREAM_SEEK_ERROR },
93 { ERROR_SHARING_BUFFER_EXCEEDED,SVSTREAM_SHARE_BUFF_EXCEEDED },
94 { ERROR_SHARING_PAUSED, SVSTREAM_SHARING_VIOLATION },
95 { ERROR_SHARING_VIOLATION, SVSTREAM_SHARING_VIOLATION },
96 { ERROR_TOO_MANY_OPEN_FILES, SVSTREAM_TOO_MANY_OPEN_FILES },
97 { ERROR_WRITE_FAULT, SVSTREAM_WRITE_ERROR },
98 { ERROR_WRITE_PROTECT, SVSTREAM_ACCESS_DENIED },
99 { ERROR_DISK_FULL, SVSTREAM_DISK_FULL },
100
101 { (DWORD)0xFFFFFFFF, SVSTREAM_GENERALERROR }
102 };
103
104 sal_uIntPtr nRetVal = SVSTREAM_GENERALERROR; // Standardfehler
105 int i=0;
106 do
107 {
108 if( errArr[i].wnt == nWntError )
109 {
110 nRetVal = errArr[i].sv;
111 break;
112 }
113 i++;
114 } while( errArr[i].wnt != (DWORD)0xFFFFFFFF );
115 return nRetVal;
116 }
117
118 /*************************************************************************
119 |*
120 |* SvFileStream::SvFileStream()
121 |*
122 |* Beschreibung STREAM.SDW
123 |* Ersterstellung OV 17.06.94
124 |* Letzte Aenderung TPF 15.07.98
125 |*
126 *************************************************************************/
127
SvFileStream(const String & rFileName,StreamMode nMode)128 SvFileStream::SvFileStream( const String& rFileName, StreamMode nMode )
129 {
130 bIsOpen = sal_False;
131 nLockCounter = 0;
132 bIsWritable = sal_False;
133 pInstanceData = new StreamData;
134
135 SetBufferSize( 8192 );
136 // convert URL to SystemPath, if necessary
137 ::rtl::OUString aFileName, aNormPath;
138
139 if ( FileBase::getSystemPathFromFileURL( rFileName, aFileName ) != FileBase::E_None )
140 aFileName = rFileName;
141 Open( aFileName, nMode );
142 }
143
144 /*************************************************************************
145 |*
146 |* SvFileStream::SvFileStream()
147 |*
148 |* Beschreibung STREAM.SDW
149 |* Ersterstellung OV 22.11.94
150 |* Letzte Aenderung TPF 15.07.98
151 |*
152 *************************************************************************/
153
SvFileStream()154 SvFileStream::SvFileStream()
155 {
156 bIsOpen = sal_False;
157 nLockCounter = 0;
158 bIsWritable = sal_False;
159 pInstanceData = new StreamData;
160
161 SetBufferSize( 8192 );
162 }
163
164 /*************************************************************************
165 |*
166 |* SvFileStream::~SvFileStream()
167 |*
168 |* Beschreibung STREAM.SDW
169 |* Ersterstellung OV 14.06.94
170 |* Letzte Aenderung OV 14.06.94
171 |*
172 *************************************************************************/
173
~SvFileStream()174 SvFileStream::~SvFileStream()
175 {
176 Close();
177 if (pInstanceData)
178 delete pInstanceData;
179 }
180
181 /*************************************************************************
182 |*
183 |* SvFileStream::GetFileHandle()
184 |*
185 |* Beschreibung STREAM.SDW
186 |* Ersterstellung OV 14.06.94
187 |* Letzte Aenderung OV 14.06.94
188 |*
189 *************************************************************************/
190
GetFileHandle() const191 sal_uIntPtr SvFileStream::GetFileHandle() const
192 {
193 return (sal_uIntPtr)pInstanceData->hFile;
194 }
195
196 /*************************************************************************
197 |*
198 |* SvFileStream::IsA()
199 |*
200 |* Beschreibung STREAM.SDW
201 |* Ersterstellung OV 14.06.94
202 |* Letzte Aenderung OV 14.06.94
203 |*
204 *************************************************************************/
205
IsA() const206 sal_uInt16 SvFileStream::IsA() const
207 {
208 return ID_FILESTREAM;
209 }
210
211 /*************************************************************************
212 |*
213 |* SvFileStream::GetData()
214 |*
215 |* Beschreibung STREAM.SDW, Prueft nicht Eof; IsEof danach rufbar
216 |* Ersterstellung OV 15.06.94
217 |* Letzte Aenderung TPF 15.07.98
218 |*
219 *************************************************************************/
220
GetData(void * pData,sal_uIntPtr nSize)221 sal_uIntPtr SvFileStream::GetData( void* pData, sal_uIntPtr nSize )
222 {
223 DWORD nCount = 0;
224 if( IsOpen() )
225 {
226 bool bResult = ReadFile(pInstanceData->hFile,(LPVOID)pData,nSize,&nCount,NULL);
227 if( !bResult )
228 {
229 sal_uIntPtr nTestError = GetLastError();
230 SetError(::GetSvError( nTestError ) );
231 }
232 }
233 return (DWORD)nCount;
234 }
235
236 /*************************************************************************
237 |*
238 |* SvFileStream::PutData()
239 |*
240 |* Beschreibung STREAM.SDW
241 |* Ersterstellung OV 15.06.94
242 |* Letzte Aenderung TPF 15.07.98
243 |*
244 *************************************************************************/
245
PutData(const void * pData,sal_uIntPtr nSize)246 sal_uIntPtr SvFileStream::PutData( const void* pData, sal_uIntPtr nSize )
247 {
248 DWORD nCount = 0;
249 if( IsOpen() )
250 {
251 if(!WriteFile(pInstanceData->hFile,(LPVOID)pData,nSize,&nCount,NULL))
252 SetError(::GetSvError( GetLastError() ) );
253 }
254 return nCount;
255 }
256
257 /*************************************************************************
258 |*
259 |* SvFileStream::SeekPos()
260 |*
261 |* Beschreibung STREAM.SDW
262 |* Ersterstellung OV 15.06.94
263 |* Letzte Aenderung TPF 15.07.98
264 |*
265 *************************************************************************/
266
SeekPos(sal_uIntPtr nPos)267 sal_uIntPtr SvFileStream::SeekPos( sal_uIntPtr nPos )
268 {
269 DWORD nNewPos = 0;
270 if( IsOpen() )
271 {
272 if( nPos != STREAM_SEEK_TO_END )
273 // 64-Bit files werden nicht unterstuetzt
274 nNewPos=SetFilePointer(pInstanceData->hFile,nPos,NULL,FILE_BEGIN);
275 else
276 nNewPos=SetFilePointer(pInstanceData->hFile,0L,NULL,FILE_END);
277
278 if( nNewPos == 0xFFFFFFFF )
279 {
280 SetError(::GetSvError( GetLastError() ) );
281 nNewPos = 0L;
282 }
283 }
284 else
285 SetError( SVSTREAM_GENERALERROR );
286 return (sal_uIntPtr)nNewPos;
287 }
288
289 /*************************************************************************
290 |*
291 |* SvFileStream::Tell()
292 |*
293 |* Beschreibung STREAM.SDW
294 |* Ersterstellung OV 15.06.94
295 |* Letzte Aenderung OV 15.06.94
296 |*
297 *************************************************************************/
298 /*
299 sal_uIntPtr SvFileStream::Tell()
300 {
301 sal_uIntPtr nPos = 0L;
302
303 if( IsOpen() )
304 {
305 DWORD nPos;
306 nPos = SetFilePointer(pInstanceData->hFile,0L,NULL,FILE_CURRENT);
307 if( nPos = 0xFFFFFFFF )
308 {
309 SetError( ::GetSvError( GetLastError() ) );
310 nPos = 0L;
311 }
312 }
313 return nPos;
314 }
315 */
316
317 /*************************************************************************
318 |*
319 |* SvFileStream::FlushData()
320 |*
321 |* Beschreibung STREAM.SDW
322 |* Ersterstellung OV 15.06.94
323 |* Letzte Aenderung TPF 15.07.98
324 |*
325 *************************************************************************/
326
FlushData()327 void SvFileStream::FlushData()
328 {
329 if( IsOpen() )
330 {
331 if( !FlushFileBuffers(pInstanceData->hFile) )
332 SetError(::GetSvError(GetLastError()));
333 }
334 }
335
336 /*************************************************************************
337 |*
338 |* SvFileStream::LockRange()
339 |*
340 |* Beschreibung STREAM.SDW
341 |* Ersterstellung OV 15.06.94
342 |* Letzte Aenderung TPF 15.07.98
343 |*
344 *************************************************************************/
345
LockRange(sal_uIntPtr nByteOffset,sal_uIntPtr nBytes)346 sal_Bool SvFileStream::LockRange( sal_uIntPtr nByteOffset, sal_uIntPtr nBytes )
347 {
348 bool bRetVal = false;
349 if( IsOpen() )
350 {
351 bRetVal = ::LockFile(pInstanceData->hFile,nByteOffset,0L,nBytes,0L );
352 if( !bRetVal )
353 SetError(::GetSvError(GetLastError()));
354 }
355 return bRetVal;
356 }
357
358 /*************************************************************************
359 |*
360 |* SvFileStream::UnlockRange()
361 |*
362 |* Beschreibung STREAM.SDW
363 |* Ersterstellung OV 15.06.94
364 |* Letzte Aenderung TPF 15.07.98
365 |*
366 *************************************************************************/
367
UnlockRange(sal_uIntPtr nByteOffset,sal_uIntPtr nBytes)368 sal_Bool SvFileStream::UnlockRange( sal_uIntPtr nByteOffset, sal_uIntPtr nBytes )
369 {
370 bool bRetVal = false;
371 if( IsOpen() )
372 {
373 bRetVal = ::UnlockFile(pInstanceData->hFile,nByteOffset,0L,nBytes,0L );
374 if( !bRetVal )
375 SetError(::GetSvError(GetLastError()));
376 }
377 return bRetVal;
378 }
379
380 /*************************************************************************
381 |*
382 |* SvFileStream::LockFile()
383 |*
384 |* Beschreibung STREAM.SDW
385 |* Ersterstellung OV 15.06.94
386 |* Letzte Aenderung OV 15.06.94
387 |*
388 *************************************************************************/
389
LockFile()390 sal_Bool SvFileStream::LockFile()
391 {
392 sal_Bool bRetVal = sal_False;
393 if( !nLockCounter )
394 {
395 if( LockRange( 0L, LONG_MAX ) )
396 {
397 nLockCounter = 1;
398 bRetVal = sal_True;
399 }
400 }
401 else
402 {
403 nLockCounter++;
404 bRetVal = sal_True;
405 }
406 return bRetVal;
407 }
408
409 /*************************************************************************
410 |*
411 |* SvFileStream::UnlockFile()
412 |*
413 |* Beschreibung STREAM.SDW
414 |* Ersterstellung OV 15.06.94
415 |* Letzte Aenderung OV 15.06.94
416 |*
417 *************************************************************************/
418
UnlockFile()419 sal_Bool SvFileStream::UnlockFile()
420 {
421 sal_Bool bRetVal = sal_False;
422 if( nLockCounter > 0)
423 {
424 if( nLockCounter == 1)
425 {
426 if( UnlockRange( 0L, LONG_MAX ) )
427 {
428 nLockCounter = 0;
429 bRetVal = sal_True;
430 }
431 }
432 else
433 {
434 nLockCounter--;
435 bRetVal = sal_True;
436 }
437 }
438 return bRetVal;
439 }
440
441
442 /*************************************************************************
443 |*
444 |* SvFileStream::Open()
445 |*
446 |* Beschreibung STREAM.SDW
447 |* Ersterstellung OV 15.06.94
448 |* Letzte Aenderung TPF 15.07.98
449 |*
450 *************************************************************************/
451 /*
452 NOCREATE TRUNC NT-Action
453 ----------------------------------------------
454 0 (Create) 0 OPEN_ALWAYS
455 0 (Create) 1 CREATE_ALWAYS
456 1 0 OPEN_EXISTING
457 1 1 TRUNCATE_EXISTING
458 */
459
Open(const String & rFilename,StreamMode nMode)460 void SvFileStream::Open( const String& rFilename, StreamMode nMode )
461 {
462 String aParsedFilename(rFilename);
463
464 SetLastError( ERROR_SUCCESS );
465 Close();
466 SvStream::ClearBuffer();
467
468 eStreamMode = nMode;
469 eStreamMode &= ~STREAM_TRUNC; // beim ReOpen nicht cutten
470
471 // !!! NoOp: Ansonsten ToAbs() verwendern
472 // !!! DirEntry aDirEntry( rFilename );
473 // !!! aFilename = aDirEntry.GetFull();
474 aFilename = aParsedFilename;
475 #ifdef BOOTSTRAP
476 ByteString aFileNameA( aFilename, gsl_getSystemTextEncoding());
477 #else
478 ByteString aFileNameA( aFilename, osl_getThreadTextEncoding());
479 FSysRedirector::DoRedirect( aFilename );
480 #endif
481 SetLastError( ERROR_SUCCESS ); // ggf. durch Redirector geaendert!
482
483 /*
484 #ifdef DBG_UTIL
485 String aTraceStr( "SvFileStream::Open(): " );
486 aTraceStr += aFilename;
487 DBG_TRACE( aTraceStr );
488 #endif
489 */
490
491 DWORD nOpenAction;
492 DWORD nShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
493 DWORD nAccessMode = 0L;
494 UINT nOldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX );
495
496 if( nMode & STREAM_SHARE_DENYREAD)
497 nShareMode &= ~FILE_SHARE_READ;
498
499 if( nMode & STREAM_SHARE_DENYWRITE)
500 nShareMode &= ~FILE_SHARE_WRITE;
501
502 if( nMode & STREAM_SHARE_DENYALL)
503 nShareMode = 0;
504
505 if( (nMode & STREAM_READ) )
506 nAccessMode |= GENERIC_READ;
507 if( (nMode & STREAM_WRITE) )
508 nAccessMode |= GENERIC_WRITE;
509
510 if( nAccessMode == GENERIC_READ ) // ReadOnly ?
511 nMode |= STREAM_NOCREATE; // wenn ja, nicht erzeugen
512
513 // Zuordnung siehe obige Wahrheitstafel
514 if( !(nMode & STREAM_NOCREATE) )
515 {
516 if( nMode & STREAM_TRUNC )
517 nOpenAction = CREATE_ALWAYS;
518 else
519 nOpenAction = OPEN_ALWAYS;
520 }
521 else
522 {
523 if( nMode & STREAM_TRUNC )
524 nOpenAction = TRUNCATE_EXISTING;
525 else
526 nOpenAction = OPEN_EXISTING;
527 }
528
529 pInstanceData->hFile = CreateFile(
530 aFileNameA.GetBuffer(),
531 nAccessMode,
532 nShareMode,
533 (LPSECURITY_ATTRIBUTES)NULL,
534 nOpenAction,
535 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
536 (HANDLE) NULL
537 );
538
539 if( pInstanceData->hFile!=INVALID_HANDLE_VALUE && (
540 // Hat Create Always eine existierende Datei ueberschrieben ?
541 GetLastError() == ERROR_ALREADY_EXISTS ||
542 // Hat Open Always eine neue Datei angelegt ?
543 GetLastError() == ERROR_FILE_NOT_FOUND ))
544 {
545 // wenn ja, dann alles OK
546 if( nOpenAction == OPEN_ALWAYS || nOpenAction == CREATE_ALWAYS )
547 SetLastError( ERROR_SUCCESS );
548 }
549
550 // Bei Fehler pruefen, ob wir lesen duerfen
551 if( (pInstanceData->hFile==INVALID_HANDLE_VALUE) &&
552 (nAccessMode & GENERIC_WRITE))
553 {
554 sal_uIntPtr nErr = ::GetSvError( GetLastError() );
555 if(nErr==SVSTREAM_ACCESS_DENIED || nErr==SVSTREAM_SHARING_VIOLATION)
556 {
557 nMode &= (~STREAM_WRITE);
558 nAccessMode = GENERIC_READ;
559 // OV, 28.1.97: Win32 setzt die Datei auf 0-Laenge, wenn
560 // die Openaction CREATE_ALWAYS ist!!!!
561 nOpenAction = OPEN_EXISTING;
562 SetLastError( ERROR_SUCCESS );
563 pInstanceData->hFile = CreateFile(
564 aFileNameA.GetBuffer(),
565 GENERIC_READ,
566 nShareMode,
567 (LPSECURITY_ATTRIBUTES)NULL,
568 nOpenAction,
569 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
570 (HANDLE) NULL
571 );
572 if( GetLastError() == ERROR_ALREADY_EXISTS )
573 SetLastError( ERROR_SUCCESS );
574 }
575 }
576
577 if( GetLastError() != ERROR_SUCCESS )
578 {
579 bIsOpen = sal_False;
580 SetError(::GetSvError( GetLastError() ) );
581 }
582 else
583 {
584 bIsOpen = sal_True;
585 // pInstanceData->bIsEof = sal_False;
586 if( nAccessMode & GENERIC_WRITE )
587 bIsWritable = sal_True;
588 }
589 SetErrorMode( nOldErrorMode );
590 }
591
592 /*************************************************************************
593 |*
594 |* SvFileStream::ReOpen()
595 |*
596 |* Beschreibung STREAM.SDW
597 |* Ersterstellung OV 15.06.94
598 |* Letzte Aenderung OV 15.06.94
599 |*
600 *************************************************************************/
601
ReOpen()602 void SvFileStream::ReOpen()
603 {
604 if( !bIsOpen && aFilename.Len() )
605 Open( aFilename, eStreamMode );
606 }
607
608 /*************************************************************************
609 |*
610 |* SvFileStream::Close()
611 |*
612 |* Beschreibung STREAM.SDW
613 |* Ersterstellung OV 15.06.94
614 |* Letzte Aenderung TPF 15.07.98
615 |*
616 *************************************************************************/
617
Close()618 void SvFileStream::Close()
619 {
620 if( IsOpen() )
621 {
622 if( nLockCounter )
623 {
624 nLockCounter = 1;
625 UnlockFile();
626 }
627 Flush();
628 CloseHandle( pInstanceData->hFile );
629 }
630 bIsOpen = sal_False;
631 nLockCounter= 0;
632 bIsWritable = sal_False;
633 SvStream::ClearBuffer();
634 SvStream::ClearError();
635 }
636
637 /*************************************************************************
638 |*
639 |* SvFileStream::ResetError()
640 |*
641 |* Beschreibung STREAM.SDW; Setzt Filepointer auf Dateianfang
642 |* Ersterstellung OV 15.06.94
643 |* Letzte Aenderung OV 15.06.94
644 |*
645 *************************************************************************/
646
ResetError()647 void SvFileStream::ResetError()
648 {
649 SvStream::ClearError();
650 }
651
652 /*************************************************************************
653 |*
654 |* SvFileStream::SetSize()
655 |*
656 |* Beschreibung STREAM.SDW
657 |* Ersterstellung OV 19.10.95
658 |* Letzte Aenderung TPF 15.07.98
659 |*
660 *************************************************************************/
661
SetSize(sal_uIntPtr nSize)662 void SvFileStream::SetSize( sal_uIntPtr nSize )
663 {
664
665 if( IsOpen() )
666 {
667 int bError = sal_False;
668 HANDLE hFile = pInstanceData->hFile;
669 sal_uIntPtr nOld = SetFilePointer( hFile, 0L, NULL, FILE_CURRENT );
670 if( nOld != 0xffffffff )
671 {
672 if( SetFilePointer(hFile,nSize,NULL,FILE_BEGIN ) != 0xffffffff)
673 {
674 bool bSucc = SetEndOfFile( hFile );
675 if( !bSucc )
676 bError = sal_True;
677 }
678 if( SetFilePointer( hFile,nOld,NULL,FILE_BEGIN ) == 0xffffffff)
679 bError = sal_True;
680 }
681 if( bError )
682 SetError(::GetSvError( GetLastError() ) );
683 }
684 }
685
686