Network functions please...

Blitz3D Forums/Blitz3D Programming/Network functions please...

Subirenihil(Posted 2006) [#1]
Would someone show me how to search for network games, so I can have an in-game list of available games instead of having to use the window StartNetGame() pops up.

A few functions that see what connections a computer has - like the functions that tell blitz what graphics cards a computer has.
Functions for looking through all the games currently available on the desired connection type - kinda like the ones for searching the graphics modes or files in a directory.

That way, my game can just provide a list of possible games to join and let the user choose. And the player never has to type in anything but the name of the game he is creating. He doesn't have to watch as the cool graphics disappear and a stupid StartNetGame() window appears. The network is handled behind the scenes.

Obviously, StartNetGame() uses some functions to get the information I want, but I can't find anything in blitz to get that information.

Anybody have code or share my frustrations?


jfk EO-11110(Posted 2006) [#2]
There are 3 protocols you can use to write multiplayer games: directplay, tcp and udp. It seems you want to use directplay. I have no idea about that one. You maybe want to use the free version of BLitzPlay instead, a UDP library. There is also a version of the PHP script GNET for BlitzPlay (GNet see this page menu). GNET will host IPs etc. of running games on a webserver, exactly what you want.


Baystep Productions(Posted 2006) [#3]
Yup, I've been down this lane. What you are looking for is a static server to keep all the information on available servers. Including IP's, Ping, COnnection Type, version, etc. etc. Sort of like what GameSpy Arcade is for major titles.

Gnet is Blitz's miniscule version. It will save Game Names, Server Names, and IP's only. You then use the Include functions to get that data to your game. Gnet will work for you, unless your talking about needing to host a ton of servers. Like any major online game (Halo, AA, etc.)

I use TCP and Gnet, if I had time or money, I would start my own site for hosting this info for games. Could make money to.


Subirenihil(Posted 2006) [#4]
I can't seem to find GNet anywhere. Can someone provide a link?

[EDIT] Found GNet. Forgot the link like everyone else seems to have. Besides, what I'm looking for is LAN stuff, I'm not ready to make online games yet. GNet is a Blitz game server that allows blitz games to connect to a central online server (www.blitzbasic.com/gnet/gnet.php) so other players can join or host online games.
I don't think I want to use GNet. It was a good suggestion though. Thanks for the effort.

What I want to know is how StartNetGame() is obtaining a list of games, updating that list, and obtaining a list of possible connection types (TCP/IP, IPX, modem, serial, etc.). How does it get this infomation? Is it some DX thing? or is it part of windows? How does it get the information?

Any more ideas out there? code, userlibs, something...

DirectPlay is part of DX, but I don't care whether it's DX or windows or native blitz. Just show me how to do it in B3D and I'll be happy.

I need something to tell my program all the known connection types (TCP/IP, IPX, etc). Then, once my program choses the connection type, something to list all games on that connection type WITHIN my program, however I want to display the list, NOT in that stupid StartNetGame() window. I do not want to have to type in an IP address every time I join a game, I want to be able to just choose a game and join. And I want this for a LAN not an online game.
(yea, yea, I said the same thing over and over didn't I)


Bobysait(Posted 2006) [#5]
What do you mean by "LAN" ?
local ? or just Tcp/Ip ?

if you want LAN game, you'll have to specify the Ip ...
if you run locally with your fammily reseau, i d'ont know what will you call to receive informations. Unless you get datas from a server, and here, you'll have to get out from your local connection

If you want to play with lan using Tcp and an other player on the web, you could have a database MySql you log and had a party/Ip/name of the party ... etc... It will be your server ! Then, just have to call the database to receive informations.

Don't know if you use MySql, but it should be the best way !


Subirenihil(Posted 2006) [#6]
You don't understand do you, Bobysait.

LAN - Local Area Network
TCP/IP - Transmission Control Protocol/Internet Protocol

TCP/IP is the standard protocol for network and online connections. Other protocols exist, like IPX, which is outdated.

It is NOT required to input an IP address, if you want proof, make a simple network program that inits using StartNetGame(). You will NEVER have to give ANY address information, no IP address, no computer name, no nothing, and yet you can still see all the games availiable on your network. I am on a network not connected to the internet. Besides, if I want a game between computer in my house, I don't want to send my game off to some server site just to get information that StartNetGame() gets without being online. Just play Warcraft III on you local network. Nowhere do you give it any IP information. You just click on the multiplayer button and it shows a list of all open games. I want to be able to do that kind of thing. I would like StartNetGame() to be broken into several function that don't have a stupid window. I don't know how or where StartNetGame() is getting the network information, but it is getting it and I want to know how.

Maybe Mark has some hints...


kevin8084(Posted 2006) [#7]
You need an enumeration routine...and there's just the function available in netapi32.dll. Here is the VB form:
Private Declare Function NetServerEnum Lib "netapi32" _
(ByVal servername As Long, _
ByVal level As Long, _
buf As Any, _
ByVal prefmaxlen As Long, _
entriesread As Long, _
totalentries As Long, _
ByVal servertype As Long, _
ByVal domain As Long, _
resume_handle As Long) As Long

if you want to see an example of this call in use, go to:
http://vbnet.mvps.org/index.html?code/network/netserverenum.htm

Hope this helps.
Kevin


Subirenihil(Posted 2006) [#8]
Look promising...I'll post the Blitz code if it works...


kevin8084(Posted 2006) [#9]
Here is an interesting site that has a free network library that you can use with Blitz3d.
http://www.krylarskreations.com/knl.shtml

Kevin


jfk EO-11110(Posted 2006) [#10]
Wow a livesign of Krylar! The Library looks good, tho:

"You'll shave MONTHS off of your multiuser development cycle!"

Well, not sure if my beard is really that large. :o)


kevin8084(Posted 2006) [#11]
at LEAST months. I was checking out the library and it looks like just what Subirenihil was wanting.


Subirenihil(Posted 2006) [#12]
[EDIT] This what happens when you don't read the documentation and expect the demos to show everything! Read to the bottom of this to see how to connect without any IP stuff.

Krylar looked great - until I tried to connect to the host. It needed me to input an IP address - exactly what I am trying to avoid. Like I keep saying, StartNetGame() is the only way I've found to avoid that, but it pops up a stinking window and when I'm running a fullscreen game the window is hidden, making it look like the game locked up (it doesn't lock up, its just waiting for StartNetGame(), which isn't going do anything until I exit the fullscreen so the user can see the StartNetGame() menu and choose something, which exiting fullscreen frees all my loaded images, so I have to reload them once I return to fullscreen, which is REALLY annoying.

I'm working on that netapi32.dll stuff but I'm not doing something right. Anyone know how to do this with blitz?

These are the things I have ported into blitz. Does anyone know about writing .decls? I have something wrong here, but I'm not sure whether it is in the .decls or in my code. Please debug.
(Kevin8084, The net.bb is mostly the same your link went to ported to blitz. I ported the .decls came from there too. I've never ported anything before, so I'm sure its full of bugs)

----- netapi32.decls -----
.lib "netapi32.dll"
NetServerEnum%(servername%, level%, buf%, prefmaxlen%, entriesread%, totalentries%, servertype%, domain%, resume_handle%):"NetServerEnum"
NetApiBufferFree%(buffer%):"NetApiBufferFree"

----- net.bb -----
;Windows Type used To call the Net API
Const MAX_PREFERRED_LENGTH% = -1
Const NERR_SUCCESS% = 0
Const ERROR_MORE_DATA% = 234

Const SV_TYPE_WORKSTATION% = $1
Const SV_TYPE_SERVER% = $2
Const SV_TYPE_SQLSERVER% = $4
Const SV_TYPE_DOMAIN_CTRL% = $8
Const SV_TYPE_DOMAIN_BAKCTRL% = $10
Const SV_TYPE_TIME_SOURCE% = $20
Const SV_TYPE_AFP% = $40
Const SV_TYPE_NOVELL% = $80
Const SV_TYPE_DOMAIN_MEMBER% = $100
Const SV_TYPE_PRINTQ_SERVER% = $200
Const SV_TYPE_DIALIN_SERVER% = $400
Const SV_TYPE_XENIX_SERVER% = $800
Const SV_TYPE_SERVER_UNIX% = SV_TYPE_XENIX_SERVER
Const SV_TYPE_NT% = $1000
Const SV_TYPE_WFW% = $2000
Const SV_TYPE_SERVER_MFPN% = $4000
Const SV_TYPE_SERVER_NT% = $8000
Const SV_TYPE_POTENTIAL_BROWSER% = $10000
Const SV_TYPE_BACKUP_BROWSER% = $20000
Const SV_TYPE_MASTER_BROWSER% = $40000
Const SV_TYPE_DOMAIN_MASTER% = $80000
Const SV_TYPE_SERVER_OSF% = $100000
Const SV_TYPE_SERVER_VMS% = $200000
Const SV_TYPE_WINDOWS% = $400000 ;Windows95 And above
Const SV_TYPE_DFS% = $800000 ;Root of a DFS tree
Const SV_TYPE_CLUSTER_NT% = $1000000 ;NT Cluster
Const SV_TYPE_TERMINALSERVER% = $2000000 ;Terminal Server
Const SV_TYPE_DCE% = $10000000;IBM DSS
Const SV_TYPE_ALTERNATE_XPORT% = $20000000;rtn alternate transport
Const SV_TYPE_LOCAL_LIST_ONLY% = $40000000;rtn Local only
Const SV_TYPE_DOMAIN_ENUM% = $80000000
Const SV_TYPE_ALL% = $FFFFFFFF

Const SV_PLATFORM_ID_OS2% = 400
Const SV_PLATFORM_ID_NT% = 500

;Mask applied To svX_version_major in
;order To obtain the major version number.
Const MAJOR_VERSION_MASK% = $F

Type SERVER_INFO_100
Field sv100_platform_id%
Field sv100_name%
End Type

;Declare Function NetServerEnum Lib "netapi32" _
; (ByVal servername As Long, _
; ByVal level As Long, _
; buf As Any, _
; ByVal prefmaxlen As Long, _
; entriesread As Long, _
; totalentries As Long, _
; ByVal servertype As Long, _
; ByVal domain As Long, _
; resume_handle As Long) As Long

;Declare Function NetApiBufferFree Lib "netapi32" _
; (ByVal Buffer As Long) As Long

;Declare Sub CopyMemory Lib "kernel32" _
; Alias "RtlMoveMemory" _
; (pTo As Any, uFrom As Any, _
; ByVal lSize As Long)

;Declare Function lstrlenW Lib "kernel32" _
; (ByVal lpString As Long) As Long

Global txt$
GetServers("")
Print txt$
WaitKey
End

Function Form_Load()

; Command1.Caption = "Net Server Enum"

End Function


Function Command1_Click()

; Call GetServers("")

End Function


Function GetServers%(sDomain$)

;lists all servers of the specified Type
;that are visible in a domain.

Local bufptr%=CreateBank(10024)
Local dwEntriesread%
Local dwTotalentries%
Local dwResumehandle%
Local se100.SERVER_INFO_100
Local success%
Local nStructSize%
Local cnt%

nStructSize = 8;LenB(se100)

;Call passing MAX_PREFERRED_LENGTH To have the
;API allocate required memory For the Return values.
;
;The call is enumerating all machines on the
;network (SV_TYPE_ALL); however, by Or'ing
;specific bit masks For defined types you can
;customize the returned Data. For example, a
;value of 0x00000003 combines the bit masks For
;SV_TYPE_WORKSTATION (0x00000001) And
;SV_TYPE_SERVER (0x00000002).
;
;dwServerName must be Null. The level parameter
;(100 here) specifies the Data structure being
;used (in this Case a SERVER_INFO_100 structure).
;
;The domain member is passed as Null, indicating
;machines on the primary domain are To be retrieved.
;If you decide To use this member, pass
;StrPtr("domain name"), Not the String itself.
success = NetServerEnum(0,100,bufptr,MAX_PREFERRED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)

;If all goes well
If success = NERR_SUCCESS And success <> ERROR_MORE_DATA Then

;loop through the returned Data, adding Each
;machine To the list
For cnt = 0 To dwEntriesread - 1

;get one chunk of Data And cast
;into an SERVER_INFO_100 struct
;in order To add the name To a list
PokeInt bufptr, nStructSize * cnt,se100\sv100_platform_id
PokeInt bufptr, nStructSize * cnt+4,se100\sv100_name

Txt$=txt$+Chr$(13)+GetPointerToByteStringW(se100\sv100_name)

Next

End If

;clean up regardless of success
NetApiBufferFree(bufptr)

;Return entries as sign of success
Return dwEntriesread

End Function


Function GetPointerToByteStringW$(dwData%)

Local tmp$=""
Local tmplen%

If dwData <> 0 Then

tmplen = BankSize(dwData); * 2

If tmplen <> 0 Then
For a=0 To tmplen-1
tmp$=tmp$+Chr$(PeekByte(dwdata,a))
Next

End If

End If
Return tmp$
End Function


kevin8084(Posted 2006) [#13]
Curious: did you want to create a bank that size?


kevin8084(Posted 2006) [#14]
Here you have: Local se100.SERVER_INFO_100
Did you want se100.SERVER_INFO_100 = new SERVER_INFO_100?


Subirenihil(Posted 2006) [#15]
Actually, the bank size 10024 was a remnant of an attempt to get it to work. I originally had it 1024.

I no longer need the se100. (the code above used to have it like you have it, but I changed it while attempting to fix the bug.)

The new code runs without errors, but I have no idea why success returns 87. I don't think it runs properly yet because it can't find any games - even when I start one on the same computer - and only returns a success of 87. The msdn page says that the "level" parameter for NetServerEnum needs to be 100 or 101, but either of those values causes a "memory access violation". Suggestions anyone?

Anybody know what & means on the end of VB numbers (ie 0&)?

Bug finders, get to work!

Here is my updated code, the .decls are the same:
;Windows Type used To call the Net API
Const MAX_PREFERRED_LENGTH% = -1
Const NERR_SUCCESS% = 0
Const ERROR_MORE_DATA% = 234

Const SV_TYPE_WORKSTATION% = $1
Const SV_TYPE_SERVER% = $2
Const SV_TYPE_SQLSERVER% = $4
Const SV_TYPE_DOMAIN_CTRL% = $8
Const SV_TYPE_DOMAIN_BAKCTRL% = $10
Const SV_TYPE_TIME_SOURCE% = $20
Const SV_TYPE_AFP% = $40
Const SV_TYPE_NOVELL% = $80
Const SV_TYPE_DOMAIN_MEMBER% = $100
Const SV_TYPE_PRINTQ_SERVER% = $200
Const SV_TYPE_DIALIN_SERVER% = $400
Const SV_TYPE_XENIX_SERVER% = $800
Const SV_TYPE_SERVER_UNIX% = SV_TYPE_XENIX_SERVER
Const SV_TYPE_NT% = $1000
Const SV_TYPE_WFW% = $2000
Const SV_TYPE_SERVER_MFPN% = $4000
Const SV_TYPE_SERVER_NT% = $8000
Const SV_TYPE_POTENTIAL_BROWSER% = $10000
Const SV_TYPE_BACKUP_BROWSER% = $20000
Const SV_TYPE_MASTER_BROWSER% = $40000
Const SV_TYPE_DOMAIN_MASTER% = $80000
Const SV_TYPE_SERVER_OSF% = $100000
Const SV_TYPE_SERVER_VMS% = $200000
Const SV_TYPE_WINDOWS% = $400000 ;Windows95 And above
Const SV_TYPE_DFS% = $800000 ;Root of a DFS tree
Const SV_TYPE_CLUSTER_NT% = $1000000 ;NT Cluster
Const SV_TYPE_TERMINALSERVER% = $2000000 ;Terminal Server
Const SV_TYPE_DCE% = $10000000;IBM DSS
Const SV_TYPE_ALTERNATE_XPORT% = $20000000;rtn alternate transport
Const SV_TYPE_LOCAL_LIST_ONLY% = $40000000;rtn Local only
Const SV_TYPE_DOMAIN_ENUM% = $80000000
Const SV_TYPE_ALL% = $FFFFFFFF

Const SV_PLATFORM_ID_OS2% = 400
Const SV_PLATFORM_ID_NT% = 500

;Mask applied To svX_version_major in
;order To obtain the major version number.
Const MAJOR_VERSION_MASK% = $F

Type SERVER_INFO_100
Field sv100_platform_id%
Field sv100_name%
End Type

;Declare Function NetServerEnum Lib "netapi32" _
; (ByVal servername As Long, _
; ByVal level As Long, _
; buf As Any, _
; ByVal prefmaxlen As Long, _
; entriesread As Long, _
; totalentries As Long, _
; ByVal servertype As Long, _
; ByVal domain As Long, _
; resume_handle As Long) As Long

;Declare Function NetApiBufferFree Lib "netapi32" _
; (ByVal Buffer As Long) As Long

;Declare Sub CopyMemory Lib "kernel32" _
; Alias "RtlMoveMemory" _
; (pTo As Any, uFrom As Any, _
; ByVal lSize As Long)

;Declare Function lstrlenW Lib "kernel32" _
; (ByVal lpString As Long) As Long

Global txt$
Print GetServers("")
Print txt$
WaitKey
End

Function Form_Load()

; Command1.Caption = "Net Server Enum"

End Function


Function Command1_Click()

; Call GetServers("")

End Function


Function GetServers%(sDomain$)

;lists all servers of the specified Type
;that are visible in a domain.

Local bufptr%;=CreateBank(10024)
Local dwEntriesread%
Local dwTotalentries%
Local dwResumehandle%
Local se100.SERVER_INFO_100=New SERVER_INFO_100
Local success%
Local nStructSize%
Local cnt%

nStructSize = 8;LenB(se100)

Local d1=CreateBank(8)
d2=CreateBank(Len(sdomain$))
For a=0 To Len(sdomain$)-1:PokeByte d2,a,Asc(Mid$(sdomain$,a+1,1)):Next
;Call passing MAX_PREFERRED_LENGTH To have the
;API allocate required memory For the Return values.
;
;The call is enumerating all machines on the
;network (SV_TYPE_ALL); however, by Or'ing
;specific bit masks For defined types you can
;customize the returned Data. For example, a
;value of 0x00000003 combines the bit masks For
;SV_TYPE_WORKSTATION (0x00000001) And
;SV_TYPE_SERVER (0x00000002).
;
;dwServerName must be Null. The level parameter
;(100 here) specifies the Data structure being
;used (in this Case a SERVER_INFO_100 structure).
;
;The domain member is passed as Null, indicating
;machines on the primary domain are To be retrieved.
;If you decide To use this member, pass
;StrPtr("domain name"), Not the String itself.
success = NetServerEnum(0,d1,bufptr,MAX_PREFERRED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,d2,dwResumehandle)

;If all goes well
If ((success = NERR_SUCCESS) And (success <> ERROR_MORE_DATA)) Then

;loop through the returned Data, adding Each
;machine To the list
For cnt = 0 To dwEntriesread - 1

;get one chunk of Data And cast
;into an SERVER_INFO_100 struct
;in order To add the name To a list
PokeInt bufptr, nStructSize * cnt,PeekInt(d1,0);se100\sv100_platform_id
PokeInt bufptr, nStructSize * cnt+4,PeekInt(d1,4);se100\sv100_name

Txt$=txt$+Chr$(13)+GetPointerToByteStringW(PeekInt(d1,4));se100\sv100_name)

Next

End If

;clean up regardless of success
NetApiBufferFree(bufptr)

;Return entries as sign of success
Return dwEntriesread ;change this to "Return success" if you want to see what success returns

End Function


Function GetPointerToByteStringW$(dwData%)

Local tmp$=""
Local tmplen%

If dwData <> 0 Then

tmplen = BankSize(dwData); * 2

If tmplen <> 0 Then
For a=0 To tmplen-1
tmp$=tmp$+Chr$(PeekByte(dwdata,a))
Next

End If

End If
Return tmp$
End Function


kevin8084(Posted 2006) [#16]
Error code 87 = invalid parameter


Subirenihil(Posted 2006) [#17]
Thanks kevin. That way I at least know why it doesn't return any servers.


kevin8084(Posted 2006) [#18]
no problem. Good luck on your coding!


Subirenihil(Posted 2006) [#19]
How do I send it a pointer to an array of the SERVER_INFO_100 structure? Or shouldn't a bank work just fine?

The first two parameters need to be 0, 100. The remaining parameters still need to be debugged.


kevin8084(Posted 2006) [#20]
I just ran your code and got an error 124 (invalid level error)


kevin8084(Posted 2006) [#21]
An array is, itself, a pointer to the data type that the array holds, yes? I don't think that it's needed to do more than send it the array.


Subirenihil(Posted 2006) [#22]
Yea, it did that to me once with the first code. It always gives me an 87 with the second code.

I'm tweeking the variables and the buf parameter. I'm always getting a "memory access violation" and crashing blitzcc. I'm so glad Mark separated the compiler from the editor:)


kevin8084(Posted 2006) [#23]
For error lookups, go here:
http://www.allapi.net/php/errlookup/errlookup.php

Very handy site!


Subirenihil(Posted 2006) [#24]
I'll try that then.


kevin8084(Posted 2006) [#25]
You're in Montana, yes? Chess player?


Subirenihil(Posted 2006) [#26]
Thanks for the error page.

Identifier "se100" may not be used this way.

Dim se100.SERVER_INFO_100(100);=New SERVER_INFO_100

success = NetServerEnum(0,100,se100,MAX_PREFERRED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)


kevin8084(Posted 2006) [#27]
no problem...I'm glad that sites such as that exist!


Subirenihil(Posted 2006) [#28]
Belgrade, MT

How'd you know I liked chess?


kevin8084(Posted 2006) [#29]
you ranked #6 in 2003 tournament. You were in 8th grade at the time :)


Subirenihil(Posted 2006) [#30]
The identifier error is in the success line.


kevin8084(Posted 2006) [#31]
I think that you're going to get your code working today.


Subirenihil(Posted 2006) [#32]
There were two chess tournaments i entered in 2003 (those were the only tournaments I have ever entered, more recent ones have coincided with other more important events in my life so I haven't gotten a chance to enter) one on May 3, the other was on September 27. I think I got 4rth in May, just 'cause I was nervous and let a little kid pull a seven move checkmate on me:( My little brother took first in the level beneath me. I had moved up into the next level as had all the other good chess players. My best friend won first.


Subirenihil(Posted 2006) [#33]
What place did you get in the tournament?


kevin8084(Posted 2006) [#34]
In May, Ben Darling took 1st place. Is this your best friend? The kid pulled the 7 move checkmate on you in Round 3, yes?


kevin8084(Posted 2006) [#35]
I didn't play. I haven't played chess in years (though I started when I was four years old LOL)


Subirenihil(Posted 2006) [#36]
No, I didn't play Ben Darling in May. Some little 5th grader (that was the 7 move checkmate) was the only person I lost to that day. In September, Nathan Clevidence won. I think he won in May too, but he was in the 9th-12th range. Nathan is my best friend, haven't met Ben much other than at the chess tournaments.


kevin8084(Posted 2006) [#37]
Sorry about looking into your life a little. If you are curious, do a google search for "kevin8084" and for "klee8084". These are both me. You might find the reverse engineering aspects worthwhile. Now, gotta go for a while. Later!


Subirenihil(Posted 2006) [#38]
(The 5th grader pulled the 7 move checkmate on me in round 1)

Back to topic.

How do you send an array to a function?


kevin8084(Posted 2006) [#39]
Just call the array inside of the function:

Dim a(10)

For x=0 To 9
a(x)=x
Next

doit()

WaitKey()
End

Function doit()

For x=0 To 9
Print a(x)
Next
End Function


Or, if you are worried about the scope, you can do this:

Global a[10]

For x=0 To 9
a[x]=x
Next

doit()

WaitKey()
End

Function doit()
For x=0 To 9
Print a[x]
Next
End Function



Subirenihil(Posted 2006) [#40]
Um, I don't see how that works for the code.

If you find something that works, please tell me.


Subirenihil(Posted 2006) [#41]
I just noticed that I need pointers (aka. banks) for some of the parameters instead of actual values. Success=0 (which is NERR_SUCCESS, which is exactly what you want to see). Everything seems to run great - UNTIL the program executes the End command, which causes a "Memory access violation"

Here's the new code (I have remove most of the commented code to make this a smaller post):

;Windows Type used To call the Net API
Const MAX_PREFERRED_LENGTH% = -1
Const NERR_SUCCESS% = 0
Const ERROR_MORE_DATA% = 234

Const SV_TYPE_WORKSTATION% = $1
Const SV_TYPE_SERVER% = $2
Const SV_TYPE_SQLSERVER% = $4
Const SV_TYPE_DOMAIN_CTRL% = $8
Const SV_TYPE_DOMAIN_BAKCTRL% = $10
Const SV_TYPE_TIME_SOURCE% = $20
Const SV_TYPE_AFP% = $40
Const SV_TYPE_NOVELL% = $80
Const SV_TYPE_DOMAIN_MEMBER% = $100
Const SV_TYPE_PRINTQ_SERVER% = $200
Const SV_TYPE_DIALIN_SERVER% = $400
Const SV_TYPE_XENIX_SERVER% = $800
Const SV_TYPE_SERVER_UNIX% = SV_TYPE_XENIX_SERVER
Const SV_TYPE_NT% = $1000
Const SV_TYPE_WFW% = $2000
Const SV_TYPE_SERVER_MFPN% = $4000
Const SV_TYPE_SERVER_NT% = $8000
Const SV_TYPE_POTENTIAL_BROWSER% = $10000
Const SV_TYPE_BACKUP_BROWSER% = $20000
Const SV_TYPE_MASTER_BROWSER% = $40000
Const SV_TYPE_DOMAIN_MASTER% = $80000
Const SV_TYPE_SERVER_OSF% = $100000
Const SV_TYPE_SERVER_VMS% = $200000
Const SV_TYPE_WINDOWS% = $400000 ;Windows95 And above
Const SV_TYPE_DFS% = $800000 ;Root of a DFS tree
Const SV_TYPE_CLUSTER_NT% = $1000000 ;NT Cluster
Const SV_TYPE_TERMINALSERVER% = $2000000 ;Terminal Server
Const SV_TYPE_DCE% = $10000000;IBM DSS
Const SV_TYPE_ALTERNATE_XPORT% = $20000000;rtn alternate transport
Const SV_TYPE_LOCAL_LIST_ONLY% = $40000000;rtn Local only
Const SV_TYPE_DOMAIN_ENUM% = $80000000
Const SV_TYPE_ALL% = $FFFFFFFF

Const SV_PLATFORM_ID_OS2% = 400
Const SV_PLATFORM_ID_NT% = 500

Const MAJOR_VERSION_MASK% = $F

Type SERVER_INFO_100
Field sv100_platform_id%
Field sv100_name%
End Type

Global txt$
Print GetServers("")
Print txt$
WaitKey
End

Function GetServers%(sDomain$)
Local bufptr%=CreateBank(1024)
Local dwEntriesread%=CreateBank(4)
Local dwTotalentries%=CreateBank(4)
Local dwResumehandle%
Local success%
Local nStructSize%
Local cnt%

nStructSize = 8;LenB(se100)

Local d1=CreateBank(1024)
d2=CreateBank(Len(sdomain$))
For a=0 To Len(sdomain$)-1:PokeByte d2,a,Asc(Mid$(sdomain$,a+1,1)):Next

success = NetServerEnum(0,100,bufptr,MAX_PREFERRED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)
If ((success = NERR_SUCCESS) And (success <> ERROR_MORE_DATA)) Then

For cnt = 0 To PeekInt(dwEntriesread,0) - 1
Txt$=txt$+Chr$(13)+GetPointerToByteStringW(PeekInt(bufptr,cnt*nStructSize+4));se100\sv100_name)

Next

End If

NetApiBufferFree(bufptr)

Return PeekInt(dwEntriesread,0)

End Function


Function GetPointerToByteStringW$(dwData%)

Local tmp$=""
Local tmplen%

If dwData <> 0 Then

tmplen = BankSize(dwData); * 2

If tmplen <> 0 Then
For a=0 To tmplen-1
tmp$=tmp$+Chr$(PeekByte(dwdata,a))
Next

End If

End If
Return tmp$
End Function


kevin8084(Posted 2006) [#42]
This little example shows how to set up an array of types and shows that functions can access the array without being explicitly passed a pointer:
Type mytype
	Field x#,y#,z#
End Type

Dim cool.mytype(10)

doit()

WaitKey()
End

Function doit()
cool.mytype(0)=New mytype
cool(0)\x=5
Print cool(0)\x
delete cool(0)
End Function

Ahh...I see that you posted in the interim


Subirenihil(Posted 2006) [#43]
Thanks for the code, but that's not quite what I had in mind. I was wanting to send the array of types out to the NetServerEnum - and it didn't like it.

Anyway, I figured out that my idea of using a bank was fine, the problem was that dwEntriesRead and dwTotalEntries needed to be banks too.

But there's still a problem with my code? The End statement causes a "Memory access violation"


kevin8084(Posted 2006) [#44]
I have to go offline for a bit. I will attempt to recreate your program from scratch and see if I come up with the same error...I'll post when the program is complete.

Kevin


kevin8084(Posted 2006) [#45]
So far I'm having the same luck as you...very frustrating


Subirenihil(Posted 2006) [#46]
The NetServerEnum seems to be messing up the bank, so when Blitz tries to free it it causes an error.

Insert "FreeBank bufptr" anywhere after you create the bank. FreeBank will cause an error if you insert it after the NetServerEnum. If you insert it before the NetServerEnum, then End causes an error (because End cleans up everything, including freeing existing banks) I think it NetServerEnum may be using the wrong variable initialization command - I saw something somewhere about you must use a certain command for declaring variables when creating a dll. I will look at finding the windows command to create a bank that I can send to NetServerEnum.

This is looking very promising, but the task is a little more than I expected. I hope we can get this working so that future programmers can have a more professional style networking lib at their fingertips - and our names possibly in the credits.

Thanks for all your help Kevin. It has been a pleasure knowing someone that I can work with.


Subirenihil(Posted 2006) [#47]
GRRRrrrrrr...

I think I need someone to write a dll to do this. I'd try, but I don't have anything but Blitz. This is a hint...


kevin8084(Posted 2006) [#48]
Microsoft gives out it's express edition for free. You can make dlls quite easily with the Visual C++ Express edition or Visual C# express edition.


Subirenihil(Posted 2006) [#49]
Where do I get it at (I could search but why bother when you could tell me)?

[EDIT]
Here's the download link if anybody else is curious:
Express C++


kevin8084(Posted 2006) [#50]
You can also get the Visual Basic express edition and the Visual J# express edition. Needless to say, I have them all :)


kevin8084(Posted 2006) [#51]
In your code you can stop the error messages by:
While success=$234
success = NetServerEnum(0,100,bufptr,MAX_PREFERRED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)
Wend

Simply continuing on receiving data from the function while there is still information.


Subirenihil(Posted 2006) [#52]
Oooooooooooooh!

ERROR_MORE_DATA is supposed to be $234, not 234.

Thanks Kevin!

Now, to see if I can start a server.


kevin8084(Posted 2006) [#53]
no problem


Subirenihil(Posted 2006) [#54]
Hey Kevin! I found out why adding those lines prevents the error. It SKIPS "success=NetServerEnum(0,100,..." for proof, insert a "Stop" inside the loop - the "Stop" will never get triggered.

I think you wanted to do something like this:
success=$234
While success=$234
success=NetServerEnum(0,100,bufptr,MAX_PREFERED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)
Wend

Or like this:
Repeat
success=NetServerEnum(0,100,bufptr,MAX_PREFERED_LENGTH,dwEntriesread,dwTotalentries,SV_TYPE_ALL,0,dwResumehandle)
Until success=$234

BUT I FOUND I WAS WRONG ABOUT KNL!!!
I got it to work!

I'm on a different computer from my programming one so I can't post the code right now - I'll post as so as I can.

Thanks for all your help Kevin! You're definently going to be in the credits. I could try to send you a copy of of the game if you like - if/when I finish it. Thanks!


kevin8084(Posted 2006) [#55]
Glad to have helped, Subirenihil :)


Subirenihil(Posted 2006) [#56]
Alright! I now have a program to demonstrate a no-IP network connection.

Step 1: Download and install the K-NetLib
K-NetLib

Step 2: Run this code on several computers on your network. (it's quite elaborate, but uncommented)