Index: trunk/Include/Classes/System/IO/FileStream.ab
===================================================================
--- trunk/Include/Classes/System/IO/FileStream.ab	(revision 388)
+++ trunk/Include/Classes/System/IO/FileStream.ab	(revision 391)
@@ -4,11 +4,11 @@
 /* ほんとはmiscに入れるかかファイルを分けたほうがいいかもしれないが一先ず実装 */
 Enum FileOptions
-	Asynchronous
-	DeleteOnClose
-	Encrypted
-	None
-	RandomAccess
-	SequentialScan
-	WriteThrough 
+	None = 0
+	Asynchronous = FILE_FLAG_OVERLAPPED
+	DeleteOnClose = FILE_FLAG_DELETE_ON_CLOSE
+	Encrypted = FILE_ATTRIBUTE_ENCRYPTED
+	RandomAccess = FILE_FLAG_RANDOM_ACCESS
+	SequentialScan = FILE_FLAG_SEQUENTIAL_SCAN
+	WriteThrough = FILE_FLAG_WRITE_THROUGH
 End Enum
 
@@ -75,21 +75,10 @@
 		End Select
 
-		Select Case options
-			Case FileOptions.Asynchronous
-				op=FILE_FLAG_OVERLAPPED
-			Case FileOptions.DeleteOnClose
-				op=FILE_FLAG_DELETE_ON_CLOSE
-			Case FileOptions.Encrypted
-			Case FileOptions.None
-				op=0
-			Case FileOptions.RandomAccess
-				op=FILE_FLAG_RANDOM_ACCESS
-			Case FileOptions.SequentialScan
-				op=FILE_FLAG_SEQUENTIAL_SCAN
-			Case FileOptions.WriteThrough
-				op=FILE_FLAG_WRITE_THROUGH
-		End Select
-
-		This.handle=CreateFile(path As PSTR,ac,sh,ByVal NULL,mo,op,0)
+		op = options As DWord
+		If Not Environment.OSVersion.Platform = PlatformID.Win32NT Then
+			op And= Not FILE_FLAG_OVERLAPPED
+		End If
+
+		This.handle=CreateFile(ToTCStr(path),ac,sh,ByVal NULL,mo,op,0)
 		If This.handle=INVALID_HANDLE_VALUE Then
 		'エラー処理
@@ -134,6 +123,8 @@
 	End Sub
 Public
+	/*!
+	@brief	ファイルが読み込みに対応しているかを返す
+	*/
 	Override Function CanRead() As Boolean
-		/* ファイルが読み込みに対応しているかを返す */
 		If This.fileAccess And GENERIC_READ Then
 			Return True
@@ -143,6 +134,8 @@
 	End Function
 
+	/*!
+	@brief	ファイルがシークに対応しているかを返す
+	*/
 	Override Function CanSeek() As Boolean
-		/* ファイルがシークに対応しているかを返す */
 		If GetFileType(This.handle)=FILE_TYPE_DISK Then
 			Return True
@@ -157,6 +150,8 @@
 '	End Function*/
 
+	/*!
+	@brief	ファイルが書き込みに対応しているかを返す
+	*/
 	Override Function CanWrite() As Boolean
-		/* ファイルが書き込みに対応しているかを返す */
 		If This.fileAccess And GENERIC_WRITE Then
 			Return True
@@ -168,6 +163,8 @@
 	/*Handle*/
 
+	/*!
+	@brief	ファイルが非同期操作に対応しているかを返す
+	*/
 	Function IsAsync() As Boolean
-		/* ファイルが非同期操作に対応しているかを返す */
 		If This.fileOptions And FILE_FLAG_OVERLAPPED /*FileOptions.Asynchronous*/ Then
 			Return True
@@ -178,8 +175,18 @@
 
 	Override Function Length() As Int64
+		disposedCheck()
 		If This.CanSeek() Then
-			Dim length As LARGE_INTEGER
-			length.LowPart=GetFileSize(This.handle,VarPtr(length.HighPart) As *DWord)
-			Return MAKEQWORD(length.LowPart,length.HighPart) As Int64
+			Dim length = VarPtr(Length) As *ULARGE_INTEGER
+			length->LowPart = GetFileSize(This.handle, VarPtr(length->HighPart))
+			If LODWORD(Length) = INVALID_FILE_SIZE Then
+				Dim error = GetLastError()
+				If error <> NO_ERROR Then
+'					Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
+				End If
+			End If
+			
+			If Length < 0 Then
+				Debug 'Throw OverflowException
+			End If
 		End If
 	End Function
@@ -190,4 +197,5 @@
 	
 	Override Sub Position(value As Int64)
+		disposedCheck()
 		If This.CanSeek() Then
 			If This.IsAsync() Then
@@ -202,4 +210,5 @@
 	End Sub
 	Override Function Position() As Int64
+		disposedCheck()
 		If This.CanSeek() Then
 			If This.IsAsync() Then
@@ -266,5 +275,9 @@
 
 	Override Sub Flush()
-		FlushFileBuffers(This.handle)
+		disposedCheck()
+		Dim ret = FlushFileBuffers(This.handle)
+		If ret = FALSE Then
+'			Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+		End If
 	End Sub
 
@@ -273,8 +286,4 @@
 	End Function*/
 
-	Override Function GetHashCode() As Long
-		Return ObjPtr(This) As Long
-	End Function
-
 /*	GetLifetimeService*/
 
@@ -286,4 +295,5 @@
 
 	Sub Lock(position As Int64, length As Int64)
+		disposedCheck()
 		If position < 0 Then
 			Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
@@ -296,26 +306,56 @@
 
 	Override Function Read( buffer As *Byte, offset As Long, count As Long) As Long
-		If This.CanRead() Then
-			Dim readBytes As DWord
-			If This.IsAsync() Then
-				Dim overlapped As OVERLAPPED
-				SetQWord(VarPtr(overlapped.Offset), offset)
-				Dim ret = ReadFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
+		disposedCheck()
+		If buffer = 0 Then
+'			Throw ArgumentNullException("FileStream.Read: An argument is null value.", "buffer")
+		ElseIf Not This.CanRead() Then
+'			Throw NotSupportedException("FileStream.Read: This stream is not readable.")
+		End If
+
+		Dim ret As BOOL
+		Dim readBytes As DWord
+		If This.IsAsync() Then
+			Dim overlapped As OVERLAPPED
+			SetQWord(VarPtr(overlapped.Offset), offset)
+			overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
+			If overlapped.hEvent = 0 Then
+'				Throw OutOfMemoryException("FileStream.Read: Failed to create an event object.")
+			End If
+			Try
+				ret = ReadFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
 				If ret = FALSE Then
-					If GetLastError() = ERROR_IO_PENDING Then
-						GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
+					Dim error = GetLastError()
+					If error <> ERROR_IO_PENDING Then
+'						Detail.ThrowWinIOException("FileStream.Read: Failed to read.", error)
 					End If
 				End If
+				ret = GetOverlappedResult(This.handle, overlapped, readBytes, TRUE)
+				If ret = FALSE Then
+'					Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+				End If
 				offset += Read
-			Else
-				ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
-			End If
-			Read = readBytes As Long
-		End If
-	End Function
-
-/*	ReferenceEquals*/
-
-	Override Function Seek(offset As Int64, origin As SeekOrigin) As Long
+			Finally
+				CloseHandle(overlapped.hEvent)
+			End Try
+		Else
+			ret = ReadFile(This.handle,VarPtr(buffer[offset]),count,VarPtr(readBytes),ByVal NULL)
+			If ret = FALSE Then
+'				Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+			End If
+		End If
+		Read = readBytes As Long
+	End Function
+
+	/*!
+	@brief	ストリームの現在位置を移動させる。
+	@param[in] offset	originからの移動量
+	@param[in] origin	移動の基準位置
+	@return	移動後の新しい現在位置
+	@exception DisposedException	既にストリームが閉じられている場合
+	@exception ArgumentException	移動後の位置が負の位置（ファイル先頭より手前）になる場合
+	@exception IOException	その他エラーが発生した場合
+	*/
+	Override Function Seek(offset As Int64, origin As SeekOrigin) As Int64
+		disposedCheck()
 		If This.CanSeek() Then
 			If This.IsAsync() Then
@@ -328,16 +368,21 @@
 						This.offset = This.Length + offset
 				End Select
+				Seek = This.offset As Int64
+				If Seek < 0 Then
+'					Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
+				End If
 			Else
-				Dim seek As LARGE_INTEGER
-				seek.LowPart=LODWORD(offset)
-				seek.HighPart=HIDWORD(offset)
-				Select Case origin
-					Case SeekOrigin.Begin
-						Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_BEGIN)
-					Case SeekOrigin.Current
-						Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
-					Case SeekOrigin.End
-						Return SetFilePointer(This.handle,seek.LowPart,VarPtr(seek.HighPart) As *DWord,FILE_CURRENT)
-				End Select
+				Dim seek = VarPtr(offset) As *ULARGE_INTEGER
+				Dim ret = SetFilePointer(This.handle, seek->LowPart, VarPtr(seek->HighPart), origin As DWord)
+				If ret = INVALID_SET_FILE_POINTER Then
+					Dim error = GetLastError()
+					If error = ERROR_NEGATIVE_SEEK Then
+'						Throw ArgumentException("FileStream.Seek: Cannot seek to negative offset.")
+					ElseIf error <> NO_ERROR Then
+'						Throw Detail.ThrowWinIOException("FileStream.Seek: Failed to seek.", error)
+					End If
+				End If
+				seek->LowPart = ret
+				Seek = offset
 			End If
 		End If
@@ -349,4 +394,5 @@
 
 	Override Sub SetLength(value As Int64)
+		disposedCheck()
 		If This.CanWrite() and This.CanSeek() Then
 			If This.IsAsync() Then
@@ -354,5 +400,9 @@
 				Dim current = This.Position()
 				This.Position(value)
-				SetEndOfFile(This.handle)
+				Dim ret = SetEndOfFile(This.handle)
+				If ret = FALSE Then
+					Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+				End If
+				Position = current
 			End If
 		End If
@@ -366,4 +416,5 @@
 
 	Sub Unlock(position As Int64, length As Int64)
+		disposedCheck()
 		If position < 0 Then
 			Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(position), "position")
@@ -371,10 +422,13 @@
 			Throw New ArgumentOutOfRangeException("FileStream.Lock: An argument is negative value.", New System.Int64(length), "length")
 		End If
-		UnlockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
+		Dim ret = UnlockFile(handle, LODWORD(position As QWord), HIDWORD(position As QWord),
 			LODWORD(length As QWord), HIDWORD(length As QWord))
-	End Sub
-
+		If ret = FALSE Then
+			Detail.ThrowWinLastErrorIOException("FileStream.Read: Failed to read.")
+		End If
+	End Sub
 
 	Override Sub Write(buffer As *Byte, offset As Long, count As Long)
+		disposedCheck()
 		If This.CanWrite() Then
 			Dim writeBytes As DWord
@@ -382,11 +436,11 @@
 				Dim overlapped As OVERLAPPED
 				SetQWord(VarPtr(overlapped.Offset), offset)
+				overlapped.hEvent = CreateEvent(0, TRUE, FALSE, 0)
 				Dim ret = WriteFile(This.handle, VarPtr(buffer[offset]), count, 0, overlapped)
-				If ret = FALSE Then
-					If GetLastError() = ERROR_IO_PENDING Then
-						GetOverlappedResult(This.handle, overlapped, writeBytes, TRUE)
-					End If
+				If ret <> FALSE Or GetLastError() = ERROR_IO_PENDING Then
+					GetOverlappedResult(This.handle, overlapped, writeBytes, TRUE)
 				End If
 				offset += writeBytes
+				CloseHandle(overlapped.hEvent)
 			Else
 				WriteFile(This.handle, VarPtr(buffer[offset]), count, VarPtr(writeBytes), ByVal NULL)
@@ -394,5 +448,4 @@
 		End If
 	End Sub
-
 
 Protected
@@ -405,8 +458,11 @@
 	End Function
 
-/*	Dispose
-	Finalize
-	MemberwiseClone*/
 Private
+	Sub disposedCheck()
+		If handle = 0 Then
+'			Throw ObjectDisposedException("FileStream: This stream has closed.")
+		End If
+	End Sub
+
 End Class
 
