Valhalla Legends Forums Archive | Battle.net Bot Development | Re: [VB2005] Stops in the middle of my Sub

AuthorMessageTime
iNsaNe
There is something that I cannot figure out, and that there is some bug in my code that makes VB 2005 stop in the middle of my sub. It is C->S SID_AUTH_INFO:

[code]    Private Sub winSock_ConnectEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles winSock.ConnectEvent

        strSendData = vbNullString
        AddChat(Color.SpringGreen, "<- Connected!")

        If strProduct = "Warcraft III FT" Then

            '// C -> S 0x50 (SID_AUTH_INFO)

            winSock.SendData(Chr(1)) '// Sub Stops Here...

            InsertDWORD(&H0) '// Protocol ID (0)
            InsertNonNTString("68XI") '// Platorm ID (IX86)
            InsertNonNTString("PX3W") '// Client ID (W3XP)
            InsertDWORD(&H15) '// Version Byte
            InsertDWORD(&H0) '// Product Language
            InsertDWORD(&H0) '// Local IP address
            InsertDWORD(&H0) '// Time zone information
            InsertDWORD(&H0) '// Locale ID
            InsertDWORD(&H0) '// Language ID
            InsertNTString("USA") '// Country Abbreviation
            InsertNTString("United States") '// Country Name

            SendPacket(&H50) '// PacketID = &H50 = 0x50

        End If

    End Sub[/code]

If any visual basic 2005 users out there could point out whats going wrong.. i would appreciate it.
March 8, 2007, 6:50 AM
Myndfyr
Have you tried debugging?  I'd bet that if you stepped through line by line, you could find out which line was causing it to stop.

Visual Basic 2005 has GREAT support for this kind of thing.  It's called "setting breakpoints" and then clicking the arrow button that looks like a play icon on a VCR or DVD player for you youngsters out there.
March 8, 2007, 7:46 AM
dRAgoN
If he's useing the winsock 6.0 control, that could be the source of his problem to.
I found a few of the old controls will crash and disapear for no reason with .Net.
March 8, 2007, 6:24 PM
iNsaNe
I used breakpoints, revised it, now it passes winSock.SendData line and stops at the next one, which the problem I believe is due to CopyMemory (my question in the other topic). MakeWORD is my problem.

[code]    Public Declare Sub CopyMemory Lib "kernell32.dll" Alias "RltMoveMemory" (ByVal Destination As String, ByVal Source As Integer, ByVal Length As Long)

    Private Sub winSock_ConnectEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles winSock.ConnectEvent

        strSendData = vbNullString
        AddChat(Color.SpringGreen, "<- Connected!")

        If strProduct = "Warcraft III FT" Then Send_SIDAUTHINFO()

    End Sub

'// Now my module

    Public Sub Send_SIDAUTHINFO()

        'C -> S 0x50 (SID_AUTH_INFO)

        frmMain.winSock.SendData(&H0)

        InsertDWORD(&H0)
        InsertNonNTString("68XI") 'Platorm ID (IX86)
        InsertNonNTString("PX3W") 'Client ID (W3XP)
        InsertDWORD(&H0) 'Version Byte
        InsertDWORD(&H0) 'Product Language
        InsertDWORD(&H0) 'Local IP address
        InsertDWORD(&H0) 'Time zone information
        InsertDWORD(&H0) 'Locale ID
        InsertDWORD(&H0) 'Language ID
        InsertNTString("USA") 'Country Abbreviation
        InsertNTString("United States") 'Country Name

        SendPacket(&H50) 'PacketID = &H50 = 0x50

    End Sub

    Public Function InsertDWORD(ByVal Data As Long)

        strSendData = strSendData & MakeWORD(Data)

    End Function

    Public Function MakeWORD(ByVal Value As Short) As String

        Dim Result As String
        Result = CStr(CDbl(Result) * 2)

        CopyMemory(Result, Value, 2)
        MakeWORD = Result

    End Function[/code]

That's all the code you need to see. The code stops functioning at MakeWORD. I used Visual Basic 2005's code upgrader to convert the original MakeWORD function from VB6. Just wondering if its the Long/Short interferance or just the converter trouble or some other problem  :-\
March 9, 2007, 1:01 AM
DDA-TriCk-E
Perhaps you should use .NET's Bitconverter class instead of CopyMemory?

Also, your code says 'InsertDWORD' then you are making a WORD instead of a DWORD and I'm pretty sure dealing with a Byte Array is faster than a String in VB.NET
March 9, 2007, 1:56 AM
BreW
Please..... .NET or not, a string IS a byte array. How could it be faster?
March 9, 2007, 3:04 AM
iNsaNe
Problem solved.
March 9, 2007, 3:08 AM
BreW
Okay, what's the problem? Just incase I get stuck with .net and I encounter this problem too....
March 9, 2007, 3:17 AM
iNsaNe
Bah nvm, I have run into a stupid problem.

[code]0030  ff ff 2b 92 00 00 00 00  00 00 ff 50 35 38 30 30  ..+..... ...P5800
0040  30 30 30 36 38 58 49 50  58 33 57 30 30 30 30 30  00068XIP X3W00000
0050  30 30 30 30 30 30 30 30  30 30 30 30 30 30 30 30  00000000 00000000
0060  30 30 30 55 53 41 00 55  6e 69 74 65 64 20 53 74  000USA.U nited St
0070  61 74 65 73 00                                    ates.[/code]

All these 0's are making me cry. They wont go to "00" instead of "30".

EDIT:

Is this right? :

[code]    Public Function MakeDWORD(ByVal Value As Integer) As String

        Dim Result() As Byte
        Result = BitConverter.GetBytes(Value)

        Dim i As Integer
        For i = 0 To Result.GetUpperBound(Result(i))

            MakeDWORD = MakeDWORD & Result(i)
        Next i

    End Function[/code]
March 9, 2007, 4:15 AM
bethra
EDIT:  0x30 = 48 = ascii value of the character 0.

I'm guessing it's because your treating them as strings.
March 9, 2007, 4:27 AM
iNsaNe
[quote author=Sorc.Polgara link=topic=16449.msg166467#msg166467 date=1173414436]
EDIT:  0x30 = 48 = ascii value of the character 0.

I'm guessing it's because your treating them as strings.
[/quote]

It's [code]InsertDWORD(ByVal Data as Long)[/code]

How can I change these to "00" ... I don't see where I'm treating them as strings. I'm looking at all the codes on this forum and I do not see a difference.
March 9, 2007, 4:56 AM
Myndfyr
[quote author=brew link=topic=16449.msg166463#msg166463 date=1173410247]
Okay, what's the problem? Just incase I get stuck with .net and I encounter this problem too....
[/quote]
That's because you're wrong:

[quote author=brew link=topic=16449.msg166460#msg166460 date=1173409483]
Please..... .NET or not, a string IS a byte array. How could it be faster?
[/quote]
In .NET, a string is NOT a byte array.  A string is an array of Unicode characters, each of which is two bytes wide.

Not to mention that strings in .NET are immutable.  That means once declared, they cannot be changed.  When you make an assignment like this:
[code]
// C#
string abc = "abc";
abc = abc + "def";
' VB
Dim abc As String = "abc"
abc = abc & "def"
[/code]
what actually happens is that a string is allocated in the CLR that says "abc".  That string is, by itself, about 16 bytes (some internal state, a marker to the runtime object type, and then two bytes for length and two bytes per character - .NET strings are stored wide Pascal style).  Then, on the second line, the CLR allocates a string "def" which takes the same amount of space.  And then, the CLR allocates a third string variable of about 22 bytes (7 * 2 bytes for the text + length prefix and 8 bytes for internal state), and that's what the variable abc finally gets the reference to.  The CLR string "abc" and the CLR string "def" are marked for garbage collection at the end of the method's execution because they no longer have outstanding referenced (unless they're used as constants elsewhere in code, in which case they're interned - for more information look up .NET String Internment).

The end result of making lots of allocations like this is that you end up with a LOT of generation 0 garbage collections, resulting in poor performance and high memory usage.  On the other hand, if you use byte arrays, or one idea I'm considering is using a List<byte[]>, or EVEN BETTER is a MemoryStream since that dynamically resizes according to performance research and a logarithic formula which has been shown to be efficient (you'll notice that this is the way that JinxBot's DataBuffer works, designed after spending lots of time in CLR Profiler).
March 9, 2007, 5:39 AM
bethra
[quote author=iNsaNe link=topic=16449.msg166468#msg166468 date=1173416170]
[quote author=Sorc.Polgara link=topic=16449.msg166467#msg166467 date=1173414436]
EDIT:  0x30 = 48 = ascii value of the character 0.

I'm guessing it's because your treating them as strings.
[/quote]

It's [code]InsertDWORD(ByVal Data as Long)[/code]

How can I change these to "00" ... I don't see where I'm treating them as strings. I'm looking at all the codes on this forum and I do not see a difference.
[/quote]

Well all of the code you've been looking at on the forum has likely been VB6 code and not VB.NET.

And the common VB6 way of adding data to a buffer is by treating everything as a string.

So, your code:

[code]
Public Function InsertDWORD(ByVal Data As Long)

        strSendData = strSendData & MakeWORD(Data)

End Function
[/code]

Thus, someone correct me if I'm wrong, the above code is treating the WORD (2 bytes) returned by MakeWORD() as a string because it's typecasting the WORD to a string and concatenating it to variable strSendData, which I'm assuming is a String.  I'm not familiar with .NET, so I could be wrong.

But yeah, stop treating the buffer (strSendData) as a string, and treat it as a byte array.

EDIT:  Why the hell is InsertDWORD() calling MakeWORD()?  I'm assuming that's what was causing this topic's original problem, which you fixed.
March 9, 2007, 5:47 AM
iNsaNe
That's not my code. I changed it:

[code]    Public Function MakeDWORD(ByVal Value As Integer) As String

        Dim Result() As Byte
        Result = BitConverter.GetBytes(Value)

        Dim i As Integer
        For i = 0 To Result.GetUpperBound(Result(i))

            MakeDWORD = MakeDWORD & Result(i)
        Next i

    End Function[/code]

And I'm not sure if it has errors or not, but I feel it is working. The only problem is is that when I go to pause, I go to check strSendData (yes its a string), and each array is set to 0. That is why there are so many 0's. I am trying to convert them so they are "." and I can't figure out how.

[code]000068XIPX3W000000000000000000000000USA.United States.[/code]
March 9, 2007, 5:56 AM
Myndfyr
Part of the problem is that you're using the concatenate (&) operator.  When you concatenate a number and a string, the number is converted to string.  That's why you're seeing the 0s there.

Allow me to suggest using MBNCSUtil - using the DataReader/DataBuffer or derived classes rather than the VB6 garbage.  VB6 packet handling code simply does not translate to .NET.

[quote author=iNsaNe link=topic=16449.msg166475#msg166475 date=1173419810]
That is why there are so many 0's. I am trying to convert them so they are "." and I can't figure out how.
[/quote]
You don't want the literal character ".".  That's what packet capture tools use to represent values that aren't ASCII.
March 9, 2007, 6:02 AM
iNsaNe
That's C#... it doesn't help me with Visual Basic.

[quote author=MyndFyre[vL] link=topic=16449.msg166476#msg166476 date=1173420148]
You don't want the literal character ".".  That's what packet capture tools use to represent values that aren't ASCII.
[/quote]

I know. I'm just saying I want that to show up when I'm using Ethereal.
March 9, 2007, 6:17 AM
bethra
[quote author=MyndFyre[vL] link=topic=16449.msg166476#msg166476 date=1173420148]
Part of the problem is that you're using the concatenate (&) operator.  When you concatenate a number and a string, the number is converted to string.  That's why you're seeing the 0s there.
[/quote]That's what I tried to say.  But he didn't seem to understand.

@iNsaNe

The problem you're having is because numerical values are being converted to their string representation.  So, the number 0 is being converted to the string "0".  Similarly, the number 1337 would be converted to the string "1337".  Do you understand what we're saying?

Using the string concatenation operator & with non-strings means that it'll automatically convert the non-string data to a string and concatenate it to the left operand.
March 9, 2007, 6:21 AM
iNsaNe
Yes, I understand, and have been understanding. The only thing I don't understand is how to keep the numbers and the strings seperate yet sending them together with battle.net.
March 9, 2007, 6:26 AM
Myndfyr
[quote author=iNsaNe link=topic=16449.msg166477#msg166477 date=1173421021]
That's C#... it doesn't help me with Visual Basic.
[/quote]

1.) Even if item (2) didn't apply, if you were using VB6 you could still use the MBNCSUtil library, because MBNCSUtil is exposed to COM.
2.) The entire point of the .NET Framework is so that you can use code written in other languages easily in your project.  All you need to do is download MBNCSUtil.dll, add a reference to it in your project, and you can use all the classes from it you need.  For instance:

[code]

Imports MBNCSUtil.*

... (in a method somewhere)
Dim pck0x50 As New BncsPacket(&H50)
pck0x50.InsertInt32(0)
pck0x50.InsertDwordString("IX86")
pck0x50.InsertDwordString("STAR")
pck0x50.InsertInt32(&Hcd)
pck0x50.InsertInt32(0)
pck0x50.InsertInt32(0)
pck0x50.InsertInt32(0)
pck0x50.InsertInt32(1033)
pck0x50.InsertDwordString("enUS")
pck0x50.InsertCString("USA")
pck0x50.InsertCString("United States")

sck.Send(pck0x50.GetData())
[/code]
March 9, 2007, 6:26 AM
bethra
Not to downplay your suggestion Mynd, even though efficiency-wise and ease-wise it's the better option, but it would probably be more beneficial from an educational point of view for him to at least figure out how to do it without using MBNCSutil FIRST.
March 9, 2007, 6:32 AM
bethra
iNsaNe, you're better off rewriting the code that builds the packet.  I can't 100% tell if you're using a packet buffer class based on the code you've given, or just stuck a lot of variables, functions, and subs in a module.

I'll try get you started on helping yourself revamp your code by giving you some advice and code snipplets.

First, I suggest you import the System.IO and System.Text namespaces so that you can use the MemoryStream class and Encoding class easily.  Like MyndFyre has pointed out previously, utilizing .NET's MemoryStream class is good.

Importing these goes like this:
[code]
Imports System.IO
Imports System.Text
[/code]

Now, you're going to want to scrap the concept of having strSendData as a string, and make it instead a MemoryStream.

So where ever you have declared strSendData, scrap it and replace it with something along the lines of:

[code]
Private msBuffer As New MemoryStream
[/code]

Now take a look at this code:

[code]
Public Sub InsertDWORD(ByVal Data As Integer)
        msBuffer.Write(BitConverter.GetBytes(Data), 0, 4)
End Sub
[/code]

Notice that unlike your VB6 code and since this is VB.NET, you don't really need that MakeDWORD and MakeWORD function anymore.

Now let's see if you can take it from here.

You will probably need to use the Visual Studio documentation for reference purposes, and I suggest you try and see if you can at least get an idea of what some of the methods in MyndFyre's C# DataBuffer class are doing.  For example, understanding the methods InsertCString() and InsertDwordString() will help with rewriting InsertNTString() and InsertNonNTString() respectively.

I do hope you at least attempt this, since I have spent more than an hour refamiliarizing myself with VB and doing some reading on the .NET framework to attempt to help you.  It's been years since I've touched anything VB.  I rewrote DarkMinion's VB6 PacketBuffer class to adhere to VB.NET... DarkMinion... boy that brought back memories... oh and yeah credit goes to MyndFyre's C# DataBuffer class which I used as a guide.
March 9, 2007, 9:36 AM
Myndfyr
[quote author=Sorc.Polgara link=topic=16449.msg166481#msg166481 date=1173421943]
Not to downplay your suggestion Mynd, even though efficiency-wise and ease-wise it's the better option, but it would probably be more beneficial from an educational point of view for him to at least figure out how to do it without using MBNCSutil FIRST.
[/quote]

You can't imagine the level of frustration I've garnered with people trying to use VB.NET who try to use code they got from another VB6 bot.  Especially now that Microsoft has made VB 2005 freely available in the Express edition.
March 9, 2007, 3:49 PM
dRAgoN
[quote author=MyndFyre[vL] link=topic=16449.msg166487#msg166487 date=1173455356]
[quote author=Sorc.Polgara link=topic=16449.msg166481#msg166481 date=1173421943]
Not to downplay your suggestion Mynd, even though efficiency-wise and ease-wise it's the better option, but it would probably be more beneficial from an educational point of view for him to at least figure out how to do it without using MBNCSutil FIRST.
[/quote]

You can't imagine the level of frustration I've garnered with people trying to use VB.NET who try to use code they got from another VB6 bot.  Especially now that Microsoft has made VB 2005 freely available in the Express edition.
[/quote]
Standerd versions of 2k2 and 2k3 were also downloadable from microsoft.
March 9, 2007, 5:25 PM
BreW
VB 2005 .NET is silly, why do people even bother using it? It took the RAD right out of visual basic. If you want another nice(er) OOP lang, go for C#
March 9, 2007, 8:34 PM
Barabajagal
Or, if you still like the BASIC series, PowerBasic.
March 9, 2007, 9:01 PM
bethra
Actually, since using VB.NET a bit the last day I'm pretty satisfied at how it is now compared to VB6, which I'll forever despise for giving me bad programming habits in HS.  .NET improved it a lot in my opinion.  However I agree that you'd be better off learning C#.NET than VB.NET.
March 10, 2007, 1:20 AM
iNsaNe
Wow. I'm still having problems. It stops after everytime i use msBuffer (Private msBuffer = new MemoryStream)
[code]Public Sub Send_SIDAUTHINFO()

        'C -> S 0x50 (SID_AUTH_INFO)

        frmMain.winSock.SendData(&H0)

        InsertDWORD(&H0) 'Protocol ID (0)
        InsertNonNTString("68XI") 'Platorm ID (IX86)
        InsertNonNTString("PX3W") 'Client ID (W3XP)
        InsertDWORD(&H0) 'Version Byte
        InsertDWORD(&H0) 'Product Language
        InsertDWORD(&H0) 'Local IP address
        InsertDWORD(&H0) 'Time zone information
        InsertDWORD(&H0) 'Locale ID
        InsertDWORD(&H0) 'Language ID
        InsertNTString("USA") 'Country Abbreviation
        InsertNTString("United States") 'Country Name

        SendPacket(&H50) 'PacketID = &H50 = 0x50

    End Sub

Private Sub InsertDWORD(ByVal Data As Integer)

        msBuffer.Write(BitConverter.GetBytes(Data), 0, 4)

    End Sub[/code]
March 10, 2007, 4:22 AM
bethra
First off are you using a class for building your packets?  If you aren't then... you're code is probably the epiphany of messiness and disorganization.  Also, based on the code you're given, I can't tell much to help debug the problem.
March 10, 2007, 4:26 AM
iNsaNe
It's one class named clsPacketBuffer

[code]Imports System.IO

Public Class clsPacketBuffer

    Private msBuffer As MemoryStream = New MemoryStream

    Private Sub InsertDWORD(ByVal Data As Integer)

        msBuffer.Write(BitConverter.GetBytes(Data), 0, 4)

    End Sub '<-- Sub doesn't end -.- it's my problem. I inserted breakpoint here and the debug never reaches it.

    Private Sub InsertWORD(ByVal Data As Short)

        msBuffer.Write(BitConverter.GetBytes(Data), 0, 2)

    End Sub

    Private Sub InsertByte(ByVal Data As Byte)

        msBuffer.WriteByte(Data)

    End Sub

    Private Sub InsertNonNTString(ByVal Data As String)

        msBuffer.WriteByte(Data)

    End Sub

    Private Sub InsertNTString(ByVal Data As String)

        msBuffer.WriteByte(Data & Chr(0))

    End Sub

    Public Sub Clear()

        msBuffer.Dispose()

    End Sub


    Private Sub SendPacket(ByVal PacketID As Byte)

        frmMain.winSock.SendData(msBuffer.GetBuffer)
        If PacketID = &H50 Then AddChat(Color.Yellow, "-> Sending 0x50...")

    End Sub

    Private Sub ParseData(ByVal PacketID As Long)

        'Parsing
        Select Case PacketID

            Case &H25
                AddChat(Color.SpringGreen, "< -Received: 0x25!")

            Case &H50
                AddChat(Color.SpringGreen, "<- Received: 0x50!")

        End Select
    End Sub

    Public Sub Send_SIDAUTHINFO()

        'C -> S 0x50 (SID_AUTH_INFO)

        frmMain.winSock.SendData(&H1)

        InsertDWORD(&H0) 'Protocol ID (0)
        InsertNonNTString("68XI") 'Platorm ID (IX86)
        InsertNonNTString("PX3W") 'Client ID (W3XP)
        InsertDWORD(&H0) 'Version Byte
        InsertDWORD(&H0) 'Product Language
        InsertDWORD(&H0) 'Local IP address
        InsertDWORD(&H0) 'Time zone information
        InsertDWORD(&H0) 'Locale ID
        InsertDWORD(&H0) 'Language ID
        InsertNTString("USA") 'Country Abbreviation
        InsertNTString("United States") 'Country Name

        SendPacket(&H50) 'PacketID = &H50 = 0x50
    End Sub

End Class[/code]
March 10, 2007, 7:23 AM
Myndfyr
There are quite a few problems with this code that come to mind, aside from the style issues.

The first is calling Dispose() on the MemoryStream when you call Clear().  Because of the way your buffer is constructed, as you're kind of mixing instance and non-instance style of coding, you won't be able to build more than one packet out of this buffer.  Once you do, you'll generate ObjectDisposedExceptions whenever you try to send a new packet.

The next is calling MemoryStream.GetBuffer() and sending that to the server.  Because MemoryStream doesn't allocate additional memory every time it writes, but rather allocates memory in chunks, sending the results of GetBuffer() directly over the wire will often result in extra null bytes being appended to the end of your data.  If you look at my DataBuffer class, specifically the GetData() method, you'll see:
[code]
911        public virtual byte[] GetData()
912        {
913            byte[] data = null;
914            lock (this)
915            {
916                data = new byte[m_len];
917                Buffer.BlockCopy(m_ms.GetBuffer(), 0, data, 0, m_len);
918            }
919            return data;
920        }
[/code]

This can be translated into the following VB.NET code:
[code]
Public Overridable Function GetData() As Byte()
    Dim data() As Byte
    SyncLock Me
        data = New Byte(Me.Length)
        Buffer.BlockCopy(msBuffer.GetBuffer(), 0, data, 0, Me.Length)
    End SyncLock
    Return data
End Function
[/code]

Using Buffer.BlockCopy (Buffer is a static class that provides fast copying operations to byte streams) copies the data from one byte array to another, but allows us to define the length of the copy so that we avoid the messy extra null bytes.

I'm surprised, also, that you're not generating compiler errors.  MemoryStream.WriteByte() should not compile when you pass it parameters as strings because of type incompatibility.  You should retrieve the byte representation via System.Text.Encoding.ASCII, and write that byte array to the memory stream.  That could explain why your debugger never reaches your breakpoint - if there are compilation errors that are ignored, the debugger may be trying to break on code that doesn't exist.
March 10, 2007, 8:27 AM
bethra
[quote author=MyndFyre[vL] link=topic=16449.msg166524#msg166524 date=1173515226]
I'm surprised, also, that you're not generating compiler errors.
[/quote]Me too.
March 10, 2007, 9:01 PM

Search