Ignore:
Timestamp:
Aug 21, 2008, 7:21:48 PM (16 years ago)
Author:
イグトランス (egtra)
Message:

非同期入出力(Begin/End-Read/Writeメソッド)を実装。

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ab5.0/ablib/src/Classes/System/IO/FileStream.ab

    r560 r605  
     1'Classes/System/IO/FileStream.ab
     2
    13Namespace System
    24Namespace IO
    35
    4 /* ほんとはmiscに入れるかかファイルを分けたほうがいいかもしれないが一先ず実装 */
    5 Enum FileOptions
    6     None = 0
    7     Asynchronous = FILE_FLAG_OVERLAPPED
    8     DeleteOnClose = FILE_FLAG_DELETE_ON_CLOSE
    9     Encrypted = FILE_ATTRIBUTE_ENCRYPTED
    10     RandomAccess = FILE_FLAG_RANDOM_ACCESS
    11     SequentialScan = FILE_FLAG_SEQUENTIAL_SCAN
    12     WriteThrough = FILE_FLAG_WRITE_THROUGH
    13 End Enum
     6/*
     7(handle As IntPtr, access As FileAccess)
     8(handle As IntPtr, access As FileAccess, ownsHandle As Boolean)
     9(handle As IntPtr, access As FileAccess, ownsHandle As Boolean)
     10(handle As IntPtr, access As FileAccess, ownsHandle As Boolean, isAsync As Boolean)
     11(path As String, mode As FileMode)
     12(path As String, mode As FileMode, access As FileAccess)
     13(path As String, mode As FileMode, access As FileAccess, share As FileShare, useAsync As Boolean)
     14(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions)
     15(path As String, mode As FileMode, rights As FileSystemRights, share As FileShare, options As FileOptions)
     16*/
    1417
    1518Class FileStream
    1619    Inherits Stream
    17 
    18     handle As HANDLE
    19 
    20     /*
    21     ファイルハンドルからこれらを取得できれば、これらは入らないが
    22     今のところは不明なので自前で実装するしかない
    23     */
    24     filePath As String
    25     fileMode As DWord
    26     fileAccess As DWord
    27     fileShare As DWord
    28     fileOptions As DWord
    29     ownsHandle As Boolean
    30    
    31     offset As QWord 'オーバーラップドIO用
    32 
    33     Sub _Initialize(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions)
    34         If ActiveBasic.IsNothing(path) Then
     20Protected
     21    Sub initialize(ac As DWord, owns As Boolean, isAsync As Boolean)
     22        Imports ActiveBasic
     23        ownsHandle = owns
     24        If (ac And GENERIC_READ) = 0 Then
     25            readFn = New Detail.Unreadable
     26        End If
     27        If (ac And GENERIC_WRITE) = 0 Then
     28            writeFn = New Detail.Unwritable
     29        End If
     30        If GetFileType(handle) <> FILE_TYPE_DISK Then
     31            seekFn = New Detail.Unseekable
     32        End If
     33        If isAsync Then
     34            If IsNothing(seekFn) Then
     35                seekFn = New Detail.OverlappedSeekable
     36            End If
     37            If IsNothing(readFn) Then
     38                readFn = New Detail.OverlappedReadable
     39            End If
     40            If IsNothing(writeFn) Then
     41                writeFn = New Detail.OverlappedWritable
     42            End If
     43        Else
     44            If IsNothing(seekFn) Then
     45                seekFn = New Detail.Seekable
     46            End If
     47            If IsNothing(readFn) Then
     48                readFn = New Detail.Readable
     49            End If
     50            If IsNothing(writeFn) Then
     51                writeFn = New Detail.Writable
     52            End If
     53        End If
     54    End Sub
     55
     56    Sub openFile(path As String, mode As FileMode, rights As DWord, share As FileShare, ByRef options As FileOptions)
     57        Imports ActiveBasic
     58        If IsNothing(path) Then
    3559            Throw New ArgumentNullException("path")
    3660        ElseIf path.Length = 0 Then
    37             Throw New ArgumentException
    38         End If
    39 
    40 
    41         Dim ac = access As DWord
     61            Throw New ArgumentException("path.Length = 0")
     62        End If
    4263        Dim sh = share As DWord
    4364        Dim mo = mode As DWord
    4465        Dim op = options As DWord
    45 '       If (Environment.OSVersion.Platform As DWord) <> (PlatformID.Win32NT As DWord) Then 'ToDo: なぜかアクセス違反になる
    46             op And= Not FILE_FLAG_OVERLAPPED
    47 '       End If
    48 
    49         This.handle=CreateFile(ToTCStr(path),ac,sh,ByVal NULL,mo,op,0)
    50         If This.handle=INVALID_HANDLE_VALUE Then
     66
     67        If mode = FileMode.Append Then
     68            mo = OPEN_ALWAYS
     69            seekFn = New Detail.Unseekable
     70        End If
     71
     72        Dim os = Environment.OSVersion
     73        Dim platform = os.Platform As DWord
     74        If platform = PlatformID.Win32Windows As DWord Or platform = PlatformID.Win32S As DWord Then
     75            options = (op As DWord And Not FILE_FLAG_OVERLAPPED) As FileOptions
     76        End If
     77
     78        handle = CreateFile(ToTCStr(path), rights, sh, ByVal NULL, mo, op, 0)
     79        If handle = INVALID_HANDLE_VALUE Then
    5180        'エラー処理
    5281        'Throw ArgumentException
    5382        'Throw IOException
    54         'Throw System.IO.FileNotFoundException 
    55             This.handle=0
     83        'Throw System.IO.FileNotFoundException
     84            handle = 0
    5685            Detail.ThrowWinLastErrorIOException("Failed to open/create file.")
    57             Exit Sub
    58         End If
    59 
    60         This.filePath = path
    61         This.fileMode = mo
    62         This.fileAccess = ac
    63         This.fileShare = sh
    64         This.fileOptions = op
    65         This.offset = 0
    66         This.ownsHandle = True
    67 
    68         If FileMode.Append = This.fileMode Then
     86        End If
     87   
     88        filePath = path
     89
     90        If mode = FileMode.Append Then
    6991            Seek(0, SeekOrigin.End)
    7092        End If
    7193    End Sub
    7294
     95    Sub initWithOpen(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions)
     96        openFile(path, mode, access As DWord, share, options)
     97        initialize(access, True, UseOverlappled(options))
     98    End Sub
     99
     100    Sub initWithOpen2(path As String, mode As FileMode, rights As DWord, share As FileShare, options As FileOptions)
     101        openFile(path, mode, rights, share, options)
     102        Dim ac = 0 As DWord
     103        If (rights And GENERIC_READ) Or (rights And FILE_READ_DATA) Then
     104            ac = (ac As DWord Or GENERIC_READ) As FileAccess
     105        End If
     106        If (rights And GENERIC_WRITE) Or (rights And FILE_WRITE_DATA) Then
     107            ac = (ac As DWord Or GENERIC_WRITE) As FileAccess
     108        End If
     109        initialize(ac, True, UseOverlappled(options))
     110    End Sub
     111
     112    Static Function UseOverlappled(options As FileOptions) As Boolean
     113        Dim op = options As DWord
     114        If op And FILE_FLAG_OVERLAPPED Then
     115            UseOverlappled = True
     116        Else
     117            UseOverlappled = False
     118        End If
     119    End Function
     120
     121    Sub FileStream()
     122    End Sub
    73123Public
    74     /* コンストラクタ.NETと同じように実装は難しい、一先ず動くものを実装したが変更が必要だと思う */
     124    /*!
     125    @brief ファイルを開く。
     126    @param[in] path ファイルパス
     127    @param[in] mode 開き方
     128    @param[in] rights 使用するアクセス権の指定
     129    @param[in] share 共有方法
     130    @param[in] option オプション
     131    @date 2008/08/21
     132    @auther Egtra
     133    */
     134    Sub FileStream(path As String, mode As FileMode, rights As Security.AccessControl.FileSystemRights, share As FileShare, options As FileOptions)
     135        initWithOpen2(path, mode, rights As DWord, share, options)
     136    End Sub
     137    /*!
     138    @brief ファイルを開く。
     139    @param[in] path ファイルパス
     140    @param[in] mode 開き方
     141    @param[in] access ファイルアクセスの指定
     142    @param[in] share 共有方法
     143    @param[in] option オプション
     144    */
    75145    Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, options As FileOptions)
    76         _Initialize( path, mode, access, share, options )
    77     End Sub
     146        initWithOpen(path, mode, access, share, options)
     147    End Sub
     148    /*!
     149    @brief ファイルを開く。
     150    @param[in] path ファイルパス
     151    @param[in] mode 開き方
     152    @param[in] access ファイルアクセスの指定
     153    @param[in] share 共有方法
     154    @param[in] useAsync 非同期にするならTrue
     155    @date 2008/08/21
     156    @auther Egtra
     157    */
     158    Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare, useAsync As Boolean)
     159        Dim options = FileOptions.None
     160        If useAsync Then
     161            options = FileOptions.Asynchronous
     162        End If
     163        initWithOpen(path, mode, access, share, options)
     164    End Sub
     165    /*!
     166    @brief ファイルを開く。
     167    @param[in] path ファイルパス
     168    @param[in] mode 開き方
     169    @param[in] access ファイルアクセスの指定
     170    @param[in] share 共有方法
     171    */
    78172    Sub FileStream(path As String, mode As FileMode, access As FileAccess, share As FileShare)
    79         _Initialize(path,mode,access,share,FileOptions.None)
    80     End Sub
     173        initWithOpen(path,mode,access,share,FileOptions.None)
     174    End Sub
     175    /*!
     176    @brief ファイルを開く。
     177    @param[in] path ファイルパス
     178    @param[in] mode 開き方
     179    @param[in] access ファイルアクセスの指定
     180    */
    81181    Sub FileStream(path As String, mode As FileMode, access As FileAccess)
    82         _Initialize(path,mode,access,FileShare.None,FileOptions.None)
    83     End Sub
     182        initWithOpen(path,mode,access,FileShare.None,FileOptions.None)
     183    End Sub
     184    /*!
     185    @brief ファイルを開く。
     186    @param[in] path ファイルパス
     187    @param[in] mode 開き方
     188    */
    84189    Sub FileStream(path As String, mode As FileMode)
    85190        Dim access As FileAccess
     
    98203                access=FileAccess.Write
    99204        End Select
    100         _Initialize(path,mode,access,FileShare.None,FileOptions.None)
    101     End Sub
    102     /*
     205        initWithOpen(path,mode,access,FileShare.None,FileOptions.None)
     206    End Sub
     207    /*!
     208    @brief 既存ハンドルを基にストリームを作る。
     209    @param[in] h ハンドル
     210    @param[in] access ファイルアクセスの指定
     211    @param[in] owns 所有権を保持するかどうか(TrueならDispose時に基のハンドルも閉じる)
     212    @param[in] isAsync 重複IOを使用するかどうか
    103213    @date 2008/02/26
    104214    @auther Egtra
    105     '不要になったら削除すること
    106     */
    107     Sub FileStream(h As HANDLE, access As FileAccess, owns As Boolean)
     215    @todo SafeFileHandle版に置き換えること
     216    */
     217    Sub FileStream(h As HANDLE, access As FileAccess, owns = True As Boolean, isAsync = False As Boolean)
    108218        handle = h
    109         fileAccess = access As DWord
    110         ownsHandle = owns
    111     End Sub
    112 
     219        initialize(access, owns, isAsync)
     220    End Sub
    113221Public
    114222    /*!
     
    116224    */
    117225    Override Function CanRead() As Boolean
    118         If This.fileAccess And GENERIC_READ Then
    119             Return True
    120         Else
    121             Return False
    122         End If
     226        Return readFn.CanRead
    123227    End Function
    124228
     
    127231    */
    128232    Override Function CanSeek() As Boolean
    129         If GetFileType(This.handle)=FILE_TYPE_DISK Then
    130             Return True
    131         Else
    132             Return False
    133         End If
    134     End Function
    135 
    136 '   Override Function CanTimeout() As Boolean
    137 '       /* ファイルがタイムアウトに対応しているかを返す */
    138 '       Return False /*今のところ対応していないのでFalse*/
    139 '   End Function*/
     233        Return seekFn.CanSeek
     234    End Function
    140235
    141236    /*!
     
    143238    */
    144239    Override Function CanWrite() As Boolean
    145         If This.fileAccess And GENERIC_WRITE Then
    146             Return True
    147         Else
    148             Return False
    149         End If
    150     End Function
    151 
     240        Return writeFn.CanWrite
     241    End Function
     242
     243    /*!
     244    @brief  保持しているハンドルを返す
     245    */
    152246    Function Handle() As HANDLE
    153247        Return handle
    154248    End Function
    155249
    156     /*!
    157     @brief  ファイルが非同期操作に対応しているかを返す
    158     */
    159     Function IsAsync() As Boolean
    160         If This.fileOptions And FILE_FLAG_OVERLAPPED /*FileOptions.Asynchronous*/ Then
    161             Return True
    162         Else
    163             Return False
    164         End If
    165     End Function
    166 
    167     Override Function Length() As Int64
    168         disposedCheck()
    169         If This.CanSeek() Then
    170             Dim length = VarPtr(Length) As *ULARGE_INTEGER
    171             length->LowPart = GetFileSize(This.handle, VarPtr(length->HighPart))
    172             If LODWORD(Length) = INVALID_FILE_SIZE Then
    173                 Dim error = GetLastError()
    174                 If error <> NO_ERROR Then
    175 '                   Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
    176                 End If
    177             End If
    178            
    179             If Length < 0 Then
    180                 Debug 'Throw OverflowException
    181             End If
    182         End If
     250    Override Function Length() As QWord
     251        disposedCheck()
     252        Length = seekFn.Length(This)
    183253    End Function
    184254
     
    186256        Return This.filePath
    187257    End Function
    188    
    189     Override Sub Position(value As Int64)
    190         disposedCheck()
    191         If This.CanSeek() Then
    192             If This.IsAsync() Then
    193                 offset = value As QWord
    194             Else
    195                 Dim position As LARGE_INTEGER
    196                 position.LowPart=LODWORD(value)
    197                 position.HighPart=HIDWORD(value)
    198                 SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_BEGIN)
    199             End If
    200         End If
    201     End Sub
    202     Override Function Position() As Int64
    203         disposedCheck()
    204         If This.CanSeek() Then
    205             If This.IsAsync() Then
    206                 Return offset As Int64
    207             Else
    208                 Dim position As LARGE_INTEGER
    209                 ZeroMemory(VarPtr(position),SizeOf(LARGE_INTEGER))
    210                 position.LowPart=SetFilePointer(This.handle,position.LowPart,VarPtr(position.HighPart) As *DWord,FILE_CURRENT)
    211                 Return MAKEQWORD(position.LowPart,position.HighPart) As Int64
    212             End If
    213         End If
    214     End Function
    215 
    216 /*  Override Sub ReadTimeout(value As Long)
    217         'TODO
    218     End Sub
    219     Override Function ReadTimeout() As Long
    220         'TODO
    221     End Function*/
    222 
     258
     259    Override Sub Position(value As QWord)
     260        disposedCheck()
     261        seekFn.Position(This, value)
     262    End Sub
     263    Override Function Position() As QWord
     264        disposedCheck()
     265        Position = seekFn.Position(This)
     266    End Function
     267
     268Public
    223269    /* Safe~Handle系の実装は要相談!! */
    224270/*  Function SafeFileHandle() As SafeFileHandle
    225271    End Function*/
    226272
    227     Override Sub WriteTimeout(value As Long)
    228         'TODO
    229     End Sub
    230     Override Function WriteTimeout() As Long
    231         'TODO
    232     End Function
    233    
    234 
    235273Public
    236274    Override Function BeginRead(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
    237         If This.IsAsync() Then
    238         Else
    239             Read(buffer,offset,count)
    240         End If
     275        disposedCheck()
     276        If buffer = 0 Then
     277            Throw New ArgumentNullException("FileStream.BeginRead", "buffer")
     278        End If
     279        BeginRead = readFn.BeginRead(This, buffer, offset, count, callback, state)
    241280    End Function
    242281
    243282    Override Function BeginWrite(buffer As *Byte, offset As Long, count As Long, callback As AsyncCallback, state As Object) As System.IAsyncResult
    244         If This.IsAsync() Then
    245         Else
    246             Write(buffer,offset,count)
    247         End If
    248     End Function
    249 
    250 /*  CreateObjRef*/
    251    
     283        disposedCheck()
     284        If buffer = 0 Then
     285            Throw New ArgumentNullException("FileStream.BeginWrite", "buffer")
     286        End If
     287        BeginWrite = writeFn.BeginWrite(This, buffer, offset, count, callback, state)
     288    End Function
     289
    252290    Override Function EndRead(asyncResult As System.IAsyncResult) As Long
    253         'TODO
     291        disposedCheck()
     292        EndRead = readFn.EndRead(This, asyncResult)
    254293    End Function
    255294
    256295    Override Sub EndWrite(asyncResult As System.IAsyncResult)
    257         'TODO
    258     End Sub
    259 
    260 /*  Equals*/
     296        disposedCheck()
     297        writeFn.EndWrite(This, asyncResult)
     298    End Sub
    261299
    262300    Override Sub Flush()
     
    264302        Dim ret = FlushFileBuffers(This.handle)
    265303        If ret = FALSE Then
    266 '           Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     304            Detail.ThrowWinLastErrorIOException("FileStream.Flush: Failed to flush.")
    267305        End If
    268306    End Sub
     
    272310    End Function*/
    273311
    274 /*  GetLifetimeService*/
    275 
    276 /*  Override Function GetType() As TypeInfo
    277         Return Super.GetType()
    278     End Function*/
    279 
    280 /*  InitializeLifetimeService*/
    281 
    282     Sub Lock(position As Int64, length As Int64)
     312    Sub Lock(position As QWord, length As QWord)
    283313        disposedCheck()
    284314        If position < 0 Then
    285             Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
     315            Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.UInt64(position), "position")
    286316        ElseIf length < 0 Then
    287             Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(length), "length")
    288         End If
    289         LockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
    290             LODWORD(length As QWord), HIDWORD(length As QWord))
     317            Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.UInt64(length), "length")
     318        End If
     319        If LockFile(handle, LODWORD(position), HIDWORD(position), LODWORD(length), HIDWORD(length)) = FALSE Then
     320            Detail.ThrowWinLastErrorIOException("FileStream.Lock: Failed to lock.")
     321        End If
    291322    End Sub
    292323
     
    294325        disposedCheck()
    295326        If buffer = 0 Then
    296             Throw New ArgumentNullException("FileStream.Read: An argument is null value.", "buffer")
    297         ElseIf Not This.CanRead() Then
    298             Throw New NotSupportedException("FileStream.Read: This stream is not readable.")
    299         End If
    300 
    301         Dim ret As BOOL
    302         Dim readBytes As DWord
    303         If This.IsAsync() Then
    304             Dim overlapped As OVERLAPPED
    305             SetQWord(VarPtr(overlapped.Offset), offset)
    306             overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
    307             If overlapped.hEvent = 0 Then
    308                 Throw New OutOfMemoryException("FileStream.Read: Failed to create an event object.")
    309             End If
    310             Try
    311                 ret = ReadFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
    312                 If ret = FALSE Then
    313                     Dim error = GetLastError()
    314                     If error <> ERROR_IO_PENDING Then
    315                         Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
    316                     End If
    317                 End If
    318                 ret = GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
    319                 If ret = FALSE Then
    320                     Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
    321                 End If
    322                 offset += Read
    323             Finally
    324                 CloseHandle(overlapped.hEvent)
    325             End Try
    326         Else
    327             ret = ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
    328             If ret = FALSE Then
    329                 Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
    330             End If
    331         End If
    332         Read = readBytes As Long
     327            Throw New ArgumentNullException("FileStream.Read", "buffer")
     328        End If
     329        Read = readFn.Read(This, buffer, offset, count)
    333330    End Function
    334331
     
    344341    Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64
    345342        disposedCheck()
    346         If This.CanSeek() Then
    347             If This.IsAsync() Then
    348                 Select Case origin
    349                     Case SeekOrigin.Begin
    350                         This.offset = offset
    351                     Case SeekOrigin.Current
    352                         This.offset += offset
    353                     Case SeekOrigin.End
    354                         This.offset = This.Length + offset
    355                 End Select
    356                 Seek = This.offset As Int64
    357                 If Seek < 0 Then
    358 '                   Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
    359                 End If
    360             Else
    361                 Dim seek = VarPtr(offset) As *ULARGE_INTEGER
    362                 Dim ret = SetFilePointer(This.handle, seek->LowPart, VarPtr(seek->HighPart), origin As DWord)
    363                 If ret = INVALID_SET_FILE_POINTER Then
    364                     Dim error = GetLastError()
    365                     If error = ERROR_NEGATIVE_SEEK Then
    366 '                       Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
    367                     ElseIf error <> NO_ERROR Then
    368 '                       Throw Detail.ThrowWinIOException("FileStream.Seek: Failed to seek.", error)
    369                     End If
    370                 End If
    371                 seek->LowPart = ret
    372                 Seek = offset
    373             End If
    374         End If
     343        Seek = seekFn.Seek(This, offset, origin)
    375344    End Function
    376345
     
    379348    End Sub*/
    380349
    381     Override Sub SetLength(value As Int64)
    382         disposedCheck()
    383         If This.CanWrite() and This.CanSeek() Then
    384             If This.IsAsync() Then
    385             Else
    386                 Dim current = This.Position()
    387                 This.Position(value)
    388                 Dim ret = SetEndOfFile(This.handle)
    389                 If ret = FALSE Then
    390                     Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
    391                 End If
    392                 Position = current
    393             End If
    394         End If
    395     End Sub
    396 
    397 /*  Synchronized*/
     350    Override Sub SetLength(value As QWord)
     351        disposedCheck()
     352        seekFn.SetLength(This, value)
     353    End Sub
    398354
    399355    Override Function ToString() As String
     
    401357    End Function
    402358
    403     Sub Unlock(position As Int64, length As Int64)
    404         disposedCheck()
    405         If position < 0 Then
    406             Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
    407         ElseIf length < 0 Then
    408             Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(length), "length")
    409         End If
    410         Dim ret = UnlockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
    411             LODWORD(length As QWord), HIDWORD(length As QWord))
     359    Sub Unlock(position As QWord, length As QWord)
     360        disposedCheck()
     361        Dim ret = UnlockFile(handle, LODWORD(position), HIDWORD(position), LODWORD(length), HIDWORD(length))
    412362        If ret = FALSE Then
    413             Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
     363            Detail.ThrowWinLastErrorIOException("FileStream.Unlock failed")
    414364        End If
    415365    End Sub
     
    417367    Override Sub Write(buffer As *Byte, offset As Long, count As Long)
    418368        disposedCheck()
    419         If This.CanWrite() Then
    420             Dim writeBytes As DWord
    421             If This.IsAsync() Then
    422                 Dim overlapped As OVERLAPPED
    423                 SetQWord(VarPtr(overlapped.Offset), offset)
    424                 overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
    425                 Dim ret = WriteFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
    426                 If ret <> FALSE Or GetLastError() = ERROR_IO_PENDING Then
    427                     GetOverlappedResult(This.handle, overlapped, writeBytes, TRUE)
    428                 End If
    429                 offset += writeBytes
    430                 CloseHandle(overlapped.hEvent)
    431             Else
    432                 WriteFile(This.handle, VarPtr(buffer[offset]), count, VarPtr(writeBytes), ByVal NULL)
    433             End If
    434         End If
     369        If buffer = 0 Then
     370            Throw New ArgumentNullException("FileStream.Write", "buffer")
     371        End If
     372        writeFn.Write(This, buffer, offset, count)
    435373    End Sub
    436374
     
    438376    Override Sub Dispose(disposing As Boolean)
    439377        If handle <> 0 Then
    440             Flush()
    441378            CloseHandle(InterlockedExchangePointer(ByVal VarPtr(handle), NULL))
    442379        End If
    443380    End Sub
    444381
    445     Override Function CreateWaitHandle() As System.Threading.WaitHandle
    446         Return New System.Threading.AutoResetEvent(False)
    447     End Function
    448 
    449 Private
    450382    Sub disposedCheck()
    451383        If handle = 0 Then
    452 '           Throw ObjectDisposedException("FileStream: This stream has closed.")
    453         End If
    454     End Sub
    455 
     384            Throw New ObjectDisposedException("FileStream: This stream has already closed.")
     385        End If
     386    End Sub
     387
     388Private
     389    handle As HANDLE
     390    seekFn As Detail.SeekFunctions
     391    readFn As Detail.ReadFunctions
     392    writeFn As Detail.WriteFunctions
     393    filePath As String
     394    ownsHandle As Boolean
    456395End Class
    457 
    458396
    459397End Namespace
Note: See TracChangeset for help on using the changeset viewer.