Solved

Visual Basic 6 Code To C++

Posted on 2004-09-18
24
504 Views
Last Modified: 2013-11-25
hello, just wondering could anyone port this app over to C++,

-Cheers!

-Nightma12




Option Explicit
Private Declare Sub Send_Message Lib "FDSTalk.dll" (ByVal strMessage As String, ByVal ip As Long, ByVal port As Long)
Private Declare Sub Service Lib "FDSTalk.dll" ()
Private Declare Sub Shutdown Lib "FDSTalk.dll" ()
Private DeclaOption Explicit
Private Declare Sub Send_Message Lib "FDSTalk.dll" (ByVal strMessage As String, ByVal ip As Long, ByVal port As Long)
Private Declare Sub Service Lib "FDSTalk.dll" ()
Private Declare Sub Shutdown Lib "FDSTalk.dll" ()
Private Declare Function Init Lib "FDSTalk.dll" (ByVal port As Long, ByVal password As String) As Boolean
Private Declare Sub Get_Response Lib "FDSTalk.dll" (ByRef response As String)

Private Type myBytes
    B1 As Byte
    B2 As Byte
    B3 As Byte
    B4 As Byte
End Type

Private Type myLong
    Val As Long
End Type


'the syntax is: FDSTalk.exe <message> Bye! <ip> <remote port> <remote pass> <local port>

Sub Main()
If Command$ = "" Then End
On Error GoTo crash
Dim sdata() As String
Dim fdsmsg As String
Dim rport As Long
Dim rpass As String
Dim ip As Long
Dim junk As String  'may use later
Dim lport As Integer

sdata = Split(Command$, " Bye! ")
fdsmsg = sdata(0)

sdata = Split(sdata(1), " ")
ip = IP2Long(sdata(0))
rport = sdata(1)
rpass = sdata(2)
lport = sdata(3)

If lport = 0 Then
    For lport = 1000 To 10000
        If Init(lport, rpass) = True Then Exit For      'if 0 then detect an open port
    Next
Else
    Init lport, rpass       'if not 0 then use given port
End If



Send_Message rpass, ip, rport


Service
junk = String$(26601, vbNullChar) 'may not be needed on the C++ side, but in VB6 Get_Response hangs if this isnt done
Get_Response junk 'just clearing the current contents of Get_Response (it gets filled up with crap when you connect)

Service
junk = String$(26601, vbNullChar) 'may not be needed on the C++ side, but in VB6 Get_Response hangs if this isnt done
Get_Response junk 'although it should be clear now, there have been reports of Get_Response failing sometimes, so better save than sorry :P



Send_Message fdsmsg, ip, rport
Send_Message "Bye", ip, rport

response junk


Shutdown

crash:
End
End Sub

Private Sub response(ByRef str As String)
Dim counter As Integer

For counter = 0 To 100
Service
str = String$(26601, vbNullChar) 'once again, may not be needed on the C++ side, but in VB6 Get_Response hangs if this isnt done
Get_Response str

If InStr("Goodbye!", str) > 0 Then
Exit For
End If


Next
End Sub

'note to experts, i got this function from google :P
Private Function IP2Long(ByVal ip As String) As Long
    ReDim parse(0 To 3) As String
    Dim B As myBytes
    Dim L As myLong
    parse = Split(ip, ".")
    B.B1 = Val(parse(0))
    B.B2 = Val(parse(1))
    B.B3 = Val(parse(2))
    B.B4 = Val(parse(3))
    LSet L = B
    IP2Long = L.Val
End Function



btw, i would just like the point out that i did not make FDSTalk.dll, it was made by a company that has now been brought out
0
Comment
Question by:Nightma12
  • 12
  • 12
24 Comments
 
LVL 19

Expert Comment

by:drichards
Comment Utility
Is there a C/C++ header and .lib file for FDSTalk or will you have to do 'LoadLibrary' and 'GetProcAddress' for the library functions?
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
yeah, i got them :)

uploading....

www.aohost.co.uk/FDSTalk.h
www.aohost.co.uk/FDSTalk.lib
0
 
LVL 19

Accepted Solution

by:
drichards earned 125 total points
Comment Utility
The C++ version looks like this.  You'll also need to add the FDSTalk.lib to the link input settings.
--------------------------------

#include "stdafx.h"
#include <string>
#include <winsock2.h>
#include "FDSTalk.h"

void Response(char *str)
{
    for ( int ii = 0; ii < 100; ii++ )
    {
        Service();
        Get_Response(str);

        if ( ::strstr(str, "Goodbye!") >= 0 ) break;
    }
}

// returns address in network bytes order - is that correct?
long IP2Long(std::string &ipString)
{
    long result = 0;
    size_t startPos = 0;
    for ( int ii = 0; ii < 4; ii++ )
    {
        size_t dot = ipString.find('.', startPos);
        int num = ::atoi(ipString.substr(startPos, dot-startPos).c_str());
        result *= 256;
        result += num;
        startPos = dot+1;
    }
    return ::htonl(result); // May not need htonl
}

void DoFDSTalk(std::string &command)
{
    //'the syntax is: FDSTalk.exe <message> Bye! <ip> <remote port> <remote pass> <local port>
    if ( command.length() == 0 ) return; // return if no command given
    size_t startPos = 0;
    size_t splitPos = command.find(" Bye! ");
    std::string fdsmsg = command.substr(startPos, splitPos-startPos);
    startPos = splitPos + 6; // skip over " Bye! "
    splitPos = command.find(' ', startPos);
    std::string strAddr = command.substr(startPos, splitPos-startPos);
    long ip = IP2Long(strAddr);
    startPos = splitPos + 1;
    splitPos = command.find(' ', startPos);
    short rport = static_cast<short>(::atoi(command.substr(startPos, splitPos-startPos).c_str()));
    startPos = splitPos + 1;
    splitPos = command.find(' ', startPos);
    std::string rpass = command.substr(startPos, splitPos-startPos);
    startPos = splitPos + 1;
    splitPos = command.find(' ', startPos);
    short lport = static_cast<short>(::atoi(command.substr(startPos, splitPos-startPos).c_str()));

    if ( lport == 0 )
    {
        for ( int ii = 1000; ii < 10000; ii++ )
        {
            if ( Init(ii, (char*)rpass.c_str()) ) break;
        }
    }
    else
    {
        Init(lport, (char*)rpass.c_str());
    }

    Send_Message((char*)rpass.c_str(), ip, rport);

    Service();
    char *junk = new char[26602];
    // Setting to zero-length string.  If you need to zero the whole array, replace
    // 'junk[0] = 0;' with '::ZeroMemory(junk, 26602);' everywhere.
    junk[0] = 0;
    Get_Response(junk);

    Service();
    junk[0] = 0;
    Get_Response(junk);

    Send_Message((char*)fdsmsg.c_str(), ip, rport);
    Send_Message("Bye", ip, rport);

    junk[0] = 0;
    Response(junk);

    Shutdown();

    delete[] junk;
}
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
dousnt a C++ program need a main()? :S
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
Yes, but I didn't know where the commane parameter comes from to kick the whole thing off, so i left the main function for you to implement.  Here's a main you can add to the bottom of the file:

int main(int argc, char *argv[])
{
   std::string command("<command string here>");
   DoFDSTalk(command);
}

You can pass the command as a parameter also:

int main(int argc, char *argv[])
{
   std::string command;
   if ( argc > 1 )
   {
      command = argv[1];
   }
   else
   {
      command = "<default string here>";
   }
   DoFDSTalk(command);
}

With this last one you can type: <progname> "This is my fds message 192.168.0.10 2000 password 1027" where progname is the C++ executable name to pass the FDSTalk command to the program.
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
FDSTalk2 error LNK2019: unresolved external symbol __imp__htonl@4 referenced in function "long __cdecl IP2Long(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?IP2Long@@YAJAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

FDSTalk2 error LNK2019: unresolved external symbol _Get_Response@4 referenced in function "void __cdecl Response(char *)" (?Response@@YAXPAD@Z)

FDSTalk2 error LNK2019: unresolved external symbol _Init@8 referenced in function "void __cdecl DoFDSTalk(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?DoFDSTalk@@YAXAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

FDSTalk2 error LNK2019: unresolved external symbol _Send_Message@12 referenced in function "void __cdecl DoFDSTalk(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?DoFDSTalk@@YAXAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

FDSTalk2 error LNK2019: unresolved external symbol _Service@0 referenced in function "void __cdecl Response(char *)" (?Response@@YAXPAD@Z)

FDSTalk2 error LNK2019: unresolved external symbol _Shutdown@0 referenced in function "void __cdecl DoFDSTalk(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?DoFDSTalk@@YAXAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)

FDSTalk2 fatal error LNK1120: 6 unresolved externals


:o

im useing the 2nd main() you gave me with the default string as ""
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
Looks like you haven't added the lib file to the linker settings, and I neglected to mention that you'd need ws2_32.lib as well for the Winsock call.  Go to the project properties (right click on the project in the Solution Explorer and select "Properties").  In the dialog, go to the "Linker->Input" page and add ws2_32.lib and fdstalk.lib on the "Additional Dependencies" line.  Just put the two names with spaces between.  If the FDSTalk.lib file is not in the project directory, you should also go to the "Linker->General" page and add the directory to the "Additional Library Directories" line.  These entries should be separated by ; if there are already entries there.

That should do it for you.  The FDSTalk.dll will also have to be in the directory with the C++ executable of on the system path.
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
ok, thanks, it has compiled fine, just gotta add support for it into my VB6 proggy and test it :)
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
www.aohost.co.uk/error.jpg

just tried the ::zerolength, and without anything, both crashed =/
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
just ran in debug mode, and it crashes on line:

   std::string strAddr = command.substr(startPos, splitPos-startPos);


value of command is {"msg"} (instead of the entire string?)

value of startPos is 5 and value of splitPos is 4294967295
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
If yo're passing it through the command line, you need to put quotes around the command of else it will juts take the first word as the parameter.  I showed this in my sample command line above.  Here is is again:

<progname> "This is my fds message 192.168.0.10 2000 password 1027"

where progname is the executable name.  If you want to run in debug, put the quoted string in the project "Configuration Properties->Debugging" page on the "Command Arguments" line.
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
Another alternative would be to concatenate all the command line strings:

    std::string command;
    for ( int ii = 1; ii < argc; ii++ )
    {
        command += argv[ii];
        command += " ";
    }

Then you could have a command line like:

<progname> This is my fds message 192.168.0.10 2000 password 1027
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 19

Expert Comment

by:drichards
Comment Utility
Of course, I left out the " Bye! " portion of the command string.  Insert as appropriate.
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
ok, cheers, i put "" around the command line string, and it worked, except for 2 more errors :)



        if ( ::strstr(str, "Goodbye!") <= 0 ) break;

i went though debug, and noticed this always seems to evaluate as true (unless theres something wrong with the counter), as the string clearly did not contain "Goodbye!" yet it still broke out of the for loop


also its crashing on

    delete[] junk;

with the error:

www.aohost.co.uk/error.jpg
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
ok, dont worry, about the first error, fixed it myself by removing the = and change < to > :)
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
If it's crashing on 'delete [] junk;' then either:

a) The FDSTalk dll is allocating the string and you cannot delete it in your program or

b) The FDSTalk dll is messing up the allocated array somehow.  You'd have to examone the pointer value and the memory block in the debugger to tell which is the case.

Do the results seem correct?
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
"Do the results seem correct?"

yes, the FDS recieves the message and returns the responses via Get_Response fine


"a) The FDSTalk dll is allocating the string and you cannot delete it in your program or"

so, if this is the case, will it be a memory leak if i dont delete the array?

"b) The FDSTalk dll is messing up the allocated array somehow.  You'd have to examone the pointer value and the memory block in the debugger to tell which is the case."

how would i check these?
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
The error you are getting indicates that the pointer value at time of deletion is not the same as after allocation.  In the debugger, check the value of 'junk' before and after all the calls to 'Get_Response', including the call in your 'Response' function.  My guess is that it changes.  If that's so, change junk to:

    char *junk = 0;

and remove:

    char *junk = new char[26602];
    // Setting to zero-length string.  If you need to zero the whole array, replace
    // 'junk[0] = 0;' with '::ZeroMemory(junk, 26602);' everywhere.
    junk[0] = 0;

If you don't have documentation on how to use the 'Get_Response' function, you'll have to experiment a bit to see how the memory is allocated.  If you have doucumentation of some sort, you should study it a bit.
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
The fact that the header declaration is:

      /*FDSTALK_API*/ void _stdcall Get_Response(char *&response);

would suggest that FDSTalk sets the pointer value internally.  Then there is the mystery of how is it managing memory so you aren't leaking all over the place.
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
ok, yes the pointer value is getting changed

ive done what you have tried but it still crashes with delete and is fine without delete

i would just run it without delete, but i am a bit worried about memory leaking now =/


i check the pointer after shutdown(), and it is not deleteing it,

how would i check if it is leaking? =/
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
If the pointer value is changing, then make the mods I suggested in previous post and get rid of delete (I should have pointed that out before).  If you don't allocate memory you can't delete it.  That does leave the question of how to free the returned data.  Without documentation, you can't tell.  There is no API to return the memory to the FDSTalk dll, so I don't know how they're doing it.  Maybe it is just leaking memory every time.  You could run it in a loop for a few hundred or thousand iterations and see if memory usage does way up.
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
hmmm, the FDS memory usage is increasing as well 0.o (but then it may be because it is getting spammed with the player_info command :P

ill compile FDSTalk.exe and add it into my VB6 program, and leave it running, see what the memory usage is like :)

ill post results/accept in a few days time :)
0
 
LVL 19

Expert Comment

by:drichards
Comment Utility
It is a poorly written component (the FDSTalk dll) if it is allocating memory and gives you no way to free it.  What is the 'Service' function for?  Does it free any memory?
0
 
LVL 1

Author Comment

by:Nightma12
Comment Utility
im not exactly sure what Service does :S, all i have, is the lib file, and the .h file, and how to use the DLL

all i really know about Service() is that it must be called before Get_Response

ill check tonight to see if it frees memory :), if it does, ill just add a lil Service() before Shutdown() :P
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now