Index: trunk/Include/com/bstring.ab
===================================================================
--- trunk/Include/com/bstring.ab	(revision 335)
+++ trunk/Include/com/bstring.ab	(revision 478)
@@ -1,6 +1,3 @@
 ' com/bstring.ab
-
-'#require <ole2.ab>
-'#require <oleauto.ab>
 
 Namespace ActiveBasic
@@ -8,5 +5,5 @@
 
 Class BString
-	'Inherits System.IDisposable, System.ICloneable
+	Implements System.IDisposable ', System.ICloneable
 Public
 	Sub BString()
@@ -19,28 +16,52 @@
 
 	Sub BString(s As BString)
-		BString.Copy(This.bs, s.bs)
-	End Sub
-
-	Sub BString(s As LPCOLESTR)
-		bs = SysAllocString(s)
+		If Not IsNothing(s) Then
+			bs = copy(s.bs)
+		End If
 	End Sub
 
 	Sub BString(s As LPCOLESTR, len As DWord)
-		bs = SysAllocStringLen(s, len)
-	End Sub
-
-	Sub BString(s As PCSTR)
-		Init(s, lstrlenA(s))
-	End Sub
-
-	Sub BString(s As PCSTR, len As DWord)
-		Dim lenBS = MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, 0, 0)
-		bs = SysAllocStringLen(0, lenBS)
-		MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, bs, lenBS)
+		If s <> 0 Then
+			bs = SysAllocStringLen(s, len)
+		End If
 	End Sub
 
 	Sub BString(s As String)
-		Init(s.StrPtr, s.Length As DWord)
-	End Sub
+		If Not IsNothing(s) Then
+			Init(s.StrPtr, s.Length As DWord)
+		End If
+	End Sub
+
+	Static Function FromBStr(bs As BSTR) As BString
+		FromBStr = New BString(bs, SysStringLen(bs))
+	End Function
+
+	Static Function FromCStr(s As PCWSTR) As BString
+		If s <> 0 Then
+			FromCStr = New BString(s, lstrlenW(s))
+		Else
+			FromCStr = New BString
+		End If
+	End Function
+
+	Static Function FromCStr(s As PCWSTR, len As DWord) As BString
+		If s <> 0 Then
+			FromCStr = New BString(s, len)
+		Else
+			FromCStr = New BString
+		End If
+	End Function
+
+	Static Function FromCStr(s As PCSTR) As BString
+		Dim dst As PCWSTR
+		Dim lenW = GetStr(s, dst)
+		FromCStr = FromCStr(s, lenW)
+	End Function
+
+	Static Function FromCStr(s As PCSTR, len As DWord) As BString
+		Dim dst As PCWSTR
+		Dim lenW = GetStr(s, len, dst)
+		FromCStr = FromCStr(s, lenW)
+	End Function
 
 	Sub ~BString()
@@ -48,21 +69,6 @@
 	End Sub
 
-	Sub Assign(bstr As BString)
-		Clear()
-		BString.Copy(This.bs, bstr.bs)
-	End Sub
-
-	Sub Assign(s As LPCOLESTR)
-		Clear()
-		s = SysAllocString(s)
-	End Sub
-
-	Sub AssignFromBStr(bstr As BSTR)
-		Clear()
-		BString.Copy(bs, bstr)
-	End Sub
-
 	Const Function Copy() As BSTR
-		BString.Copy(Copy, bs)
+		Copy = copy(bs)
 	End Function
 
@@ -76,26 +82,17 @@
 
 	Sub Clear()
-		If bs <> 0 Then
-			SysFreeString(bs)
-			bs = 0
-		End If
+		reset(0)
 	End Sub
 
 	Sub Attach(ByRef bstr As BSTR)
-		Clear()
-		BString.Move(bs, bstr)
+		reset(move(bstr))
 	End Sub
 
 	Function Detach() As BSTR
-		BString.Move(Detach, bs)
+		Detach = move(bs)
 	End Function
 
 	Function BStr() As BSTR
 		BStr = bs
-	End Function
-/*
-	Static Function Assgin(bs As BSTR) As BString
-		Assgin = New BString
-		Assgin.Assgin(bs)
 	End Function
 
@@ -104,24 +101,20 @@
 		Attach.Attach(bs)
 	End Function
-*/
+
 	Const Function Length() As DWord
-		Length = SysStringLen(bs)
+		Length = GetDWord(bs As VoidPtr - SizeOf (DWord)) 'SysStringLen(bs)
 	End Function
 
 	Const Function Operator [](i As SIZE_T) As OLECHAR
-#ifdef _DEBUG
 		If i > Length Then
-			'Throw OutOfRangeException
-		End If
-#endif
+			Throw New ArgumentOutOfRangeException("i")
+		End If
 		Return bs[i]
 	End Function
 
 	Sub Operator []=(i As SIZE_T, c As OLECHAR)
-#ifdef _DEBUG
 		If i > Length Then
-			'Throw OutOfRangeException
-		End If
-#endif
+			Throw New ArgumentOutOfRangeException("i")
+		End If
 		bs[i] = c
 	End Sub
@@ -135,21 +128,93 @@
 	End Function
 
+	Override Function Equals(o As Object) As Boolean
+		If Not IsNothing(o) Then
+			If This.GetType().Equals(o.GetType()) Then
+				Equals(o As BString)
+			End If
+		End If
+	End Function
+
+	Const Function Equals(s As BString) As Boolean
+		Equals = Compare(This, s) = 0
+	End Function
+
+	Static Function Compare(l As BString, r As BString) As Long
+		If IsNullOrEmpty(l) Then
+			If IsNullOrEmpty(r) Then
+				Compare = 0
+			Else
+				Compare = -1
+			End If
+		Else
+			If IsNullOrEmpty(bsr) Then
+				Compare = 1
+			Else
+				Compare = Strings.ChrCmp(l.bs, l.Length As SIZE_T, r.bs, r.Length As SIZE_T)
+			End If
+		End If
+	End Function
+
+	Static Function IsNullOrEmpty(s As BString)
+		If IsNothing(s) Then
+			IsNullOrEmpty = True
+		ElseIf s.bs = 0 Then
+			IsNullOrEmpty = True
+		ElseIf s.Length = 0 Then
+			IsNullOrEmpty = True
+		Else
+			IsNullOrEmpty = False
+		End If
+	End Function
+
+	Function Operator ==(s As BString) As Boolean
+		Return Compare(This, s) = 0
+	End Function
+
+	Function Operator <>(s As BString) As Boolean
+		Return Compare(This, s) <> 0
+	End Function
+
+	Function Operator <(s As BString) As Boolean
+		Return Compare(This, s) < 0
+	End Function
+
+	Function Operator <=(s As BString) As Boolean
+		Return Compare(This, s) <= 0
+	End Function
+
+	Function Operator >(s As BString) As Boolean
+		Return Compare(This, s) > 0
+	End Function
+
+	Function Operator >=(s As BString) As Boolean
+		Return Compare(This, s) >= 0
+	End Function
+
 Private
 	bs As BSTR
 
-	Sub Init(s As PCSTR, len As DWord)
-		Dim lenBS = MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, 0, 0)
-		bs = SysAllocStringLen(0, lenBS)
-		MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, bs, lenBS)
-	End Sub
-
-	Static Sub Copy(ByRef dst As BSTR, ByVal src As BSTR)
-		dst = SysAllocStringLen(src, SysStringLen(src))
-	End Sub
-
-	Static Sub Move(ByRef dst As BSTR, ByRef src As BSTR)
-		dst = src
-		src = 0
-	End Sub
+	Sub init(s As PCSTR, len As DWord)
+		If <> 0 Then
+			Dim lenBS = MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, 0, 0)
+			bs = SysAllocStringLen(0, lenBS)
+			If bs <> 0 Then
+				MultiByteToWideChar(CP_THREAD_ACP, 0, s, len As Long, bs, lenBS)
+			End If
+		End If
+	End Sub
+
+	Sub reset(newBS As BSTR)
+		Dim old = InterlockedExchangePointer(bs, newBS)
+		SysFreeString(old)
+	End Sub
+
+	Static Function copy(src As BSTR) As BSTR
+		copy = SysAllocStringLen(src, SysStringLen(src))
+	End Function
+
+	Static Function move(ByRef src As BSTR) As BSTR
+		move = InterlockedExchangePointer(src, 0)
+	End Function
 End Class
 
