---------------------------------------------------------
The Liberty Basic Newsletter - Issue #95 - APR 2002
    2002, http://groups.yahoo.com/group/lbnews/
             All Rights Reserved

          FOURTH ANNIVERSARY ISSUE!
         APRIL, 1998  -- APRIL, 2002
---------------------------------------------------------
No matter what accomplishments you achieve, somebody helped
you.    --Althea Gibson
---------------------------------------------------------
In this issue:
	2002 Liberty BASIC Challenge - polls open!
	SearchTreeForFile - API File Search 
	Tipcorner - Filedialogs
	The FILES statement
	The FILES statement in action - program file dialog
	Updating the Open Source Editor for WinXP
	Spotlight on John Fisher
	Using Winsock, code example by Brent Thorn
	Winsock API Reference, from Microsoft
	Submissions
	Volunteer to Publish the LB Newsletter
---------------------------------------------------------
---------------------------------------------------------
POLLS OPEN!

http://groups.yahoo.com/group/lbnews/polls

The submission period is over and it is time to download
the programs, try them out, and vote for one in each 
category:  newbie, oldbie, game, open

A large variety of clever programs have been entered in
this challenge.  They demonstrate the great versatility
of Liberty BASIC.

Download them here:  
http://groups.yahoo.com/group/lbnews/files/2002%20Liberty%20BASIC%20Challenge/

It is REALLY IMPORTANT to have all of our members vote.
The Challenge is about sharing.  Some folks have gone to 
a lot of trouble to share these great programs.  The rest
of us must participate and take the time to vote.  Please
cast your vote before May 1!

Before casting your votes, take a few minutes to reread
the guidelines, here:
http://groups.yahoo.com/group/lbnews/files/2002%20Liberty%20BASIC%20Challenge/2002%20Challenge

The judging criteria are listed below.  Thanks for voting!

********************************************************
JUDGING CRITERIA

1.   Programs should meet all guidelines as set forth
in this file.

2.   Programs should be as bug-free as possible.

3.   Programs should have lots of comments.

4.   Programs should be well-structured.

5.   User interfaces should be attractive and easy to use.

6.   Program should be easy to use without complicated
instructions.

7.   Programs should have unique and interesting elements
provided by the programmer.

8.   A sense of humor is important.  This should be FUN!
********************************************************
---------------------------------------------------------
---------------------------------------------------------
SEARCHTREEFORFILE - API FILE SEARCH

(LB3+ only!)

From the ebook, Mastering Liberty BASIC 3:
*****************************************
Find a file quickly with the SearchTreeForFile function from 
"imagehlp" DLL.  RootPath$ is a pointer to a null-terminated 
string that specifies the path where the function should begin 
searching for the file.  InputPathName$ is a pointer to a 
null-terminated string that specifies the file for which the 
function will search. A program can use a partial path.  
OutputPathBuffer$ is a pointer to a buffer that receives the 
full path to the file that is found. This string is not modified 
if the return value is FALSE.  Below is a small demo.  Choose to 
try searching for the filename alone, or filename with 
partial path.


RootPath$="c:\"
'InputPathName$="bmp\copy.bmp" + chr$(0) 'includes partial path
InputPathName$="liberty.exe" + chr$(0)   'filename only
OutputPathBuffer$=space$(1023)+chr$(0)

open "imagehlp" for dll as #ih
calldll #ih, "SearchTreeForFile",_
RootPath$ as ptr,_
InputPathName$ as ptr,_
OutputPathBuffer$ as ptr,_
ret as long
close #ih

print "Searching (c:\) for ";InputPathName$
if ret=0 then
print InputPathName$;" not found."
else
print "Full path is ";trim$(OutputPathBuffer$)

end if
print "Finished"
end

See below for an example of this function as it is
used in the Open Source Editor.

---------------------------------------------------------
---------------------------------------------------------
TIPCORNER - FILEDIALOGS

It is possible to use multiple extensions in a filedialog.
The code here will show both BAS and LBA files in the dialog:

filedialog "Open file..",filePath$+"*.bas;*.lba",file$ 

To show more than one extension, be sure that each one
is in the form that has an asterisk, then a dot, then the
desired extension - "*.ext".  Separate these extensions with
semi-colons.  Here are some possible template strings for 
extensions:

"*.txt;*.bas;*.dat;*.lba"
"*.bmp;*.jpg;*.gif"
"*.ini;*.log"


We can have a filedialog open in the directory of our choice by
including a path in the template string.

filedialog "Open","c:\myfiles\*.txt",file$

The template string can be a concatenation of two strings.  If it
is, then be sure that the path part of the string contains a 
backslash.  

Correct:
filedialog "Open","c:\myfiles\"+"*.txt",file$

Also Correct:
filedialog "Open","c:\myfiles" +"\*.txt",file$ 

Incorrect (lacks a backslash):
filedialog "Open","c:\myfiles"+"*.txt",file$

The path part of the string can be a string variable.  To open
a file in a program's default directory:

Correct:
filedialog "Open",DefaultDir$ +"\*.txt",file$ 

Incorrect (lacks a backslash):
fildialog "Open",DefaultDir$ + "*.txt", file$


We can take a filename that is returned from a filedialog
and separate the path from the filename.  This is useful when
we want to use the FILES command to check for a file's 
existence.  Here are two Liberty BASIC functions that accept an
argument that is a filename returned from a filedialog.  They
both parse the string with WHILE/WEND loops, looking for the
final instance of a backslash.  They begin at the end of the
filename and check each character to see if it is a backslash,
moving to the next character to the left with each iteration.
This check is done with the Mid$() function.  When a backslash
character is found, the loop terminates and the index variable
contains the position within the filename string for the
final backslash.

The SeparateFile$ function returns the information after the 
final backslash, which is the filename alone.  The SeparatePath$ 
function returns the information before the final backslash, 
which is the pathname.

Separate path and filename:

    shortFile$=SeparateFile$(file$)
    filePath$=SeparatePath$(file$)

function SeparateFile$(f$)
    fileindex=len(f$)
    filelength=len(f$)
      while mid$(f$, fileindex,1)<>"\"
        fileindex=fileindex-1
      wend
    SeparateFile$=right$(f$,filelength-fileindex)
end function


function SeparatePath$(f$)
    fileindex=len(f$)
    filelength=len(f$)
      while mid$(f$, fileindex,1)<>"\"
        fileindex=fileindex-1
      wend
    SeparatePath$=left$(f$,fileindex)
end function


Once we have the pathname and filename separated, we can check 
for file's existence before attempting to open it.  We use the
FILES statement to do this.  

We have created a special function in the Open Source Editor 
to check for a file's existence.  If the file doesn't exist, 
we don't attempt to open it, because that would cause a program 
crash!

    if FileExist(filePath$,shortFile$)<1 then
        notice "Error"+chr$(13)+"File does not exist."
        wait
    end if

The FileExist function accepts arguments of the pathname and
the filename, then uses the FILES statement to check for the
existence.  If the value of info$(0,0) is 0, then the file
doesn't exist.

function FileExist(fPath$,fFile$)
    files fPath$,fFile$,info$(
    FileExist=val(info$(0,0))
end function

---------------------------------------------------------
---------------------------------------------------------
THE FILES STATEMENT

The FILES statement collects file and directory information 
from any disk and/or directory and fills a double-dimensioned 
array with the information.  It is also good for determining 
if a specific file exists (see below).

Before you use the FILES statement, you must first dimension
a double-dimensioned string array for its use.  The name of
the array is up to you.  LB programmers often call this array
info$().

    dim info$(10, 10)
    files "c:\", info$()

The above FILES statement will fill info$( ) in this fashion:

    info$(0, 0) - a string specifying the qty of files found
    info$(0, 1) - a string specifying the qty of subdirectories found
    info$(0, 2) - the drive spec
    info$(0, 3) - the directory path

Starting at info$(1, x) you will have file information like so:

    info$(1, 0) - the file name
    info$(1, 1) - the file size
    info$(1, 2) - the file date/time stamp

"info$()" is a string array, so to get numeric values, use the VAL
function.  The quantity of files found is returned like this:

n = VAL(info$(0,0))

Knowing from info$(0, 0) how many files we have (call it n), 
we know that our subdirectory information starts at n + 1, so:

    info$(n + 1, 0) - the complete path of a dir (ie. \work\math)
    info$(n + 1, 1) - the name of the dir (ie. math)

(Directories and subdirectories are often called folders.  The names
are used interchangeably.)

You can optionally specify a wildcard.  This lets you get a list of 
all *.ini files, for example.  This is how you do it:

    files DefaultDir$, "*.ini", info$(

This also makes it practical to use to check for file existance.  
If you want to know if a file c:\config.bak exists, you could try...

    files "c:\", "config.bak", info$(

    If val(info$(0, 0)) > 0, then the file exists.

---------------------------------------------------------
---------------------------------------------------------
THE FILES STATEMENT IN ACTION - PROGRAM FILE DIALOG

This sample shows how to use the FILES statement to fill
listboxes and comboboxes to simulate a Windows filedialog.
The advantage to writing your own dialog of this type is 
that it can remain open, and it can contain other controls.
For instance, it might be used to preview wav files by
playing a wav when one is selected from the list.  You might
include a graphicbox to create a bitmap previewer.  The uses
are many for this type of window.

'some code by Ryan Jeffords, 1997

NoMainWin

    Dim dir$(10,10)
    Dim files$(300)
    Dim directory$(300)
    Dim Drive$(300)
    Dim type$(5)
    qu$ = Chr$(34)
    view = 0

    pathname$ = Mid$(DefaultDir$,3,Len(DefaultDir$))
    unit$ = Left$(DefaultDir$,2)
    fileext$ = "*.txt"

    type$(1) = "Text Files (*.TXT)"
    type$(2) = "Code Files (*.BAS)"
    type$(3) = "Bitmap Files (*.BMP)"
    type$(4) = "All Files (*.*)"

    GoSub [scanfiles]

    '** Set Window Attributes
    UpperLeftX = Int((DisplayWidth- 447)/2)
    UpperLeftY = Int((DisplayHeight- 246)/2)
    WindowWidth = 447
    WindowHeight = 246

    '** Add Window Controls
    Textbox #dirbox.filetext, 5, 20,170,25
    Listbox #dirbox.filebox, files$(, [db.InputLoop],5,55,170,105
    Combobox #dirbox.filetype, type$(, [db.filetype],5,185,170,165
    Listbox #dirbox.dirbox, directory$(, [db.InputLoop],185,20,175,138
    Combobox #dirbox.drivebox, Drive$(, [db.drivetype],185,185,175,80
    Button #dirbox.Button12, "Ok", [db.ok] , UL,365,30,70,24
    Button #dirbox.Button13, "Cancel", [db.CloseWindow],UL,364,56,70,24
    statictext #dirbox.1, "File Types:",5,162,170,20
    statictext #dirbox.2, "Drives:",185,162,170,20
    statictext #dirbox.3, "File Names:",5,1,170,20
    statictext #dirbox.4, "Folders:",185,1,170,20

    '** Display window
    Open "File Preview Dialog" For dialog As #dirbox
    Print #dirbox, "TRAPCLOSE [db.CloseWindow]"

    Print #dirbox, "font MS_Sans_Serif 0 16"; '** Set the font
    Print #dirbox.filebox, "singleclickselect [db.choosefile]"
    Print #dirbox.dirbox, "singleclickselect [db.choosedir]"

[db.AfterLoad]
Print #dirbox.drivebox, "select "; unit$
Print #dirbox.filetype, "select "; type$(1)
GoSub [redisplayfiles]


[db.InputLoop]
wait


[db.CloseWindow]
Close #dirbox : End


[db.Subroutines]
[redisplayfiles]
      Print #dirbox.dirbox, "reload"
      Print #dirbox.filebox, "reload"
Return

[scanfiles]
    index = 0
    loadname$ = unit$ + pathname$
    Files loadname$, fileext$, dir$(
    qtyFiles = Val(dir$(0, 0))
    qtySubDirs = Val(dir$(0, 1))
    ReDim files$(300)
    For x = 1 TO qtyFiles
        dir$(x,1) = Right$(dir$(x, 1), 9)
        files$(x) = Left$(dir$(x, 0),13)
    Next x
    While Word$(Drives$, index + 1) <> ""
        Drive$(index) = Word$(Drives$, index + 1)
        index = index + 1
    Wend
     ReDim directory$(300)
     directory$(0) = ". ."
     For x = qtyFiles+1  TO qtyFiles + qtySubDirs
      directory$(x) = "  " + dir$(x, 1)
     Next x
    If qtyFiles > 2 Then Sort files$(, 1, qtyFiles
Return

[truncatename]
     For z = Len(pathname$) TO 1 step -1
        If Mid$(pathname$,z,1) = "\" Then pathname$ = Left$(pathname$, z-1): z = 0
     Next z
    If Instr(pathname$,"\") = 0  Then pathname$ = "\"
Return


[db.choosefile]
    Print #dirbox.filebox ,"selection?  selection$"
    Print #dirbox.filetext, selection$
    GoSub [redisplayfiles]
    wait


[db.filetype]
    Print #dirbox.filetype ,"selection? fileext$"
    z = Instr(fileext$, "(")
    fileext$ = Mid$(fileext$, z+1, Len(fileext$)-z-1)
    GoSub [scanfiles]
    GoSub [redisplayfiles]
    wait


[db.choosedir]
   Print #dirbox.dirbox ,"selection? newdir$"
    If newdir$ <> ". ."  AND Len(pathname$) > 2 Then
        pathname$ = pathname$ + "\" + newdir$
    Else
        pathname$ = pathname$ + newdir$
    End If
    If newdir$ = ". ." Then GoSub [truncatename]
   GoSub [scanfiles]
   GoSub [redisplayfiles]
   wait


[db.drivetype]
    Print #dirbox.drivebox ,"selection? newunit$"
    unit$ = newunit$ : pathname$ ="\"
    GoSub [scanfiles]
    GoSub [redisplayfiles]
    wait

[db.ok]
Print #dirbox.filetext, "!Contents? TheName$";
Notice "Dir Info" +Chr$(13)+"File Name Selected :";TheName$ +Chr$(13)+"Directory:  "+loadname$
wait

---------------------------------------------------------
---------------------------------------------------------
UPDATING THE OPEN SOURCE EDITOR

We've now changed the "open file" and "save file" routines
to include *.lba as a possible file extension.

filedialog "Open file..",filePath$+"*.bas;*.lba",file$ 

Notice that we can have multiple extensions in a filedialog
by separating them with semi-colons.  See the FILEDIALOG
article above for details on using multiple extensions.

WINDOWS XP
Some routines that worked in Windows95/98 no longer work
in WindowsXP, so we'll try to make the Open Source Editor
work with all 32-bit versions of Windows.

We previously ran winfile.exe to run the Windows File
Manager.  Even though this was a Windows 3.1 application,
it was also available on later versions of Windows.  It is
no longer available on Windows XP.  We'll now run Windows
explorer in LB3, like this:

[winfile]
    'change to make XP compatible
    run "explorer.exe",SHOWNORMAL
    wait

We run into even more of a problem when trying to run MS Paint.
Although Windows ought to know where to find its own applications,
it doesn't seem to work properly with mspaint.  In versions of
Windows prior to XP, we could run "pbrush.exe".  This was a 16-bit
application, so Win95 and later had a small "pbrush.exe" program 
that simply ran MS Paint.  Windows XP no longer has this feature.
Simply running "mspaint.exe" doesn't work in XP, although it does work
(for me!) in Win98.  The work-around is to use the SearchTreeForFile
API call that was outlined earlier, and find the proper location for
mspaint.exe.

Be sure to read the article above about the SearchTreeForFile API call.
Here, it is implemented in the Open Source Editor to find mspaint.exe.
Notice that if the function cannot find mspaint.exe, the program will
not try to run it.  Trying to run a non-existant application with the
RUN command would cause a program crash.  Error trapping is always
very important!

[paint]
    'change to make XP compatible
    cursor hourglass
    RootPath$="c:\"
    InputPathName$="mspaint.exe" + chr$(0)   'filename only
    OutputPathBuffer$=space$(1023)+chr$(0)

    open "imagehlp" for dll as #ih
    calldll #ih, "SearchTreeForFile",_
        RootPath$ as ptr,_
        InputPathName$ as ptr,_
        OutputPathBuffer$ as ptr,_
        ret as long
        close #ih

    if ret=0 then
        notice InputPathName$;" not found."
    else
        run trim$(OutputPathBuffer$), SHOWNORMAL
    end if
    cursor normal
    wait
---------------------------------------------------------
---------------------------------------------------------
SPOTLIGHT ON JOHN FISHER

John Fisher is a Liberty BASIC programmer who has used
Liberty BASIC to accomplish some really amazing tasks.
Would you believe that Liberty BASIC could control
a bank of individual lights?  How about a program to
evaluate human reaction time?

Read all about the projects on his webpages, including 
lots of great pictures, and downloadable files!

From John Fisher's Websites:
______________________________________________________
An 8-light DiscoLitez rig controlled by Liberty Basic.
 
This is about a bar of mains lamps controlled from your 
computer's parallel printer port. It gave me a chance to 
get my computer interacting with the real world & humans 
in an impressive way. (I am a teacher...) Possibly even 
useful.. & I do come from the home of Bridgwater & 
Taunton carnivals! 

http://atschool.eduweb.co.uk/taunton/disco.htm

___________________________
Human Reaction Time Project
An on-going programming and human performance project.
Carried out at Taunton School, UK, 1990-99

The full suite of programs gathered anonymously the times 
of sets of 50 consecutive tests of reaction speed to a visual 
stimulus. In addition the sex, age and handedness were requested, 
as all three seemed likely to be associated. The results of my 
students and colleagues doing several of these 50-test runs was 
that I could average them, and analyse by sex, etc.

The original programs were written for the Acorn computers so 
widely used in the UK. I had despaired of writing such programs 
easily until I discovered Liberty BASIC for the PC & rewrote the 
LB programs. Best thing out for Windows programs- FAR easier than 
Visual BASIC for beginners to use. 

http://atschool.eduweb.co.uk/taunton/WebNotes/rtest.htm

John Fisher
ICT Co-ordinator, Taunton School
John.Fisher@TauntonSchool.co.uk
---------------------------------------------------------
---------------------------------------------------------
USING WINSOCK - CODE EXAMPLE BY BRENT THORN
	- USED BY PERMISSION
	- FOR LIBERTY BASIC 3

' IP Getter using Winsock
' Based on code at http://www.vbapi.com/ref/g/gethostbyname.html.
' By Brent Thorn, March 2002
' mailto:lbgui@aol.com

    Titlebar "IP Getter"

    Open "Kernel32" For DLL As #kernel
    Open "WSock32" For DLL As #wsock

    Domain$ = "www.yahoo.com"
    Prompt "Enter an Internet domain."; Domain$

    If Domain$ <> "" Then
        Struct sockinfo, _
            wVersion As word, _
            wHighVersion As word, _
            szDescription As char[257], _
            szSystemStatus As char[129], _
            iMaxSockets As long, _
            iMaxUdpDg As long, _
            lpVenderInfo As long
        Struct hostinfo, _
            hname As long, _
            haliases As long, _
            haddrtype As word, _
            hlength As word, _
            haddrlist As long
        Struct sIPAddress, _
            number As ulong

        ' Open up a Winsock session, using version 2.2.
        wVersionRequested = MAKEWORD(2, 2)
        CallDLL #wsock, "WSAStartup",_
            wVersionRequested As word,_
            sockinfo As struct, result As long

        If retval <> 0 Then
            Print "ERROR: Attempt to open Winsock failed: error"; retval
            GoTo [End]
        End If

        ' Get information about the domain specified in Domain$.
        pHostInfo = gethostbyname(Domain$)

        If pHostInfo = 0 Then
            Print "Unable to resolve domain name."
        Else
            ' Copy the data into a HOSTENT structure.
            length = Len(hostinfo.struct)
            CallDLL #kernel, "RtlMoveMemory",_
                hostinfo As struct, pHostInfo As ulong,_
                length As ulong, result As void

            If hostinfo.haddrtype.struct <> 2 Then
                Print "A non-IP address was returned."
            Else
                ' Copy the pointer to the first (and probably only)
                ' IP address in the structure.
                source = hostinfo.haddrlist.struct
                CallDLL #kernel, "RtlMoveMemory",_
                    sIPAddress As struct, source As ulong,_
                    4 As ulong, result As void

                ' Copy the actual IP address.
                source = sIPAddress.number.struct
                CallDLL #kernel, "RtlMoveMemory",_
                        sIPAddress As struct, source As ulong,_
                        4 As ulong, result As void

                ' Convert the IP address into a human-readable string.
                ipAddress = sIPAddress.number.struct
                pIPString = inet.ntoa(ipAddress)

                ' Copy the result into a string variable.
                ipString$ = WinString(pIPString)

                ' Print the result: a human-readable IP address.
                Print ipString$
            End If
        End If

        retval = WSACleanup()
    End If

[End]
    Close #kernel
    Close #wsock

    End


'*** Winsock Wrapper Functions ***

Function WSACleanup()
    CallDLL #wsock, "WSACleanup",_
    WSACleanup As long
End Function

Function gethostbyname( name$ )
    CallDLL #wsock, "gethostbyname",_
    name$ As ptr, gethostbyname As long
End Function

Function inet.ntoa( inaddr )
    CallDLL #wsock, "inet_ntoa",_
    inaddr As long, inet.ntoa As long
End Function

'*** General-purpose Routines ***

'Make a word from two bytes (0 to 255).
Function MAKEWORD( bLow, bHigh )
    MAKEWORD = bLow + 256 * bHigh
End Function
---------------------------------------------------------
---------------------------------------------------------
WINSOCK API REFERENCE - MICROSOFT

           ***************************
           ***************************
			WSAStartup

The Windows Sockets WSAStartup function initiates use of the 
Windows Sockets DLL by a process.

int WSAStartup (WORD wVersionRequested,LPWSADATA lpWSAData	);	

Parameters

wVersionRequested

[in] The highest version of Windows Sockets support that the 
caller can use. The high order byte specifies the minor version 
(revision) number; the low-order byte specifies the major version 
number.

lpWSAData

[out] A pointer to the WSADATA data structure that is to receive 
details of the Windows Sockets implementation.

Remarks

This function must be the first Windows Sockets function called by 
an application or DLL. It allows an application or DLL to specify 
the version of Windows Sockets required and to retrieve details of 
the specific Windows Sockets implementation. The application or DLL 
may only issue further Windows Sockets functions after a successful 
WSAStartup invocation.

In order to support future Windows Sockets implementations and 
applications which may have functionality differences from current 
version of Windows Sockets, a negotiation takes place in WSAStartup. 
The caller of WSAStartup and the Windows Sockets DLL indicate to each 
other the highest version that they can support, and each confirms that 
the other's highest version is acceptable. Upon entry to WSAStartup, 
the Windows Sockets DLL examines the version requested by the 
application. If this version is equal to or higher than the lowest 
version supported by the DLL, the call succeeds and the DLL returns 
in wHighVersion the highest version it supports and in wVersion the 
minimum of its high version and wVersionRequested. The Windows Sockets 
DLL then assumes that the application will use wVersion. If the wVersion 
field of the WSADATA structure is unacceptable to the caller, it should 
call WSACleanup and either search for another Windows Sockets DLL or 
fail to initialize.

This negotiation allows both a Windows Sockets DLL and a Windows Sockets 
application to support a range of Windows Sockets versions. An application 
can successfully utilize a Windows Sockets DLL if there is any overlap in 
the version ranges


           ***************************
           ***************************

			WSAData

Once an application or DLL has made a successful WSAStartup 
call, it may proceed to make other Windows Sockets calls as 
needed. When it has finished using the services of the Windows 
Sockets DLL, the application or DLL must call WSACleanup in 
order to allow the Windows Sockets DLL to free any resources 
for the application.

Details of the actual Windows Sockets implementation are described 
in the WSAData structure defined as follows:

struct WSAData {
    WORD            wVersion;
    WORD            wHighVersion;
    char            
szDescription[WSADESCRIPTION_LEN+1];
    char              szSystemStatus[WSASYSSTATUS_LEN+1];
    unsigned short    iMaxSockets;
    unsigned short    iMaxUdpDg; 
    char FAR *        lpVendorInfo;
};
 

The members of this structure are:

Parameters

wVersion

The version of the Windows Sockets specification that the Windows 
Sockets DLL expects the caller to use.

wHighVersion

The highest version of the Windows Sockets specification that this 
DLL can support (also encoded as above). Normally this will be the 
same as wVersion.

sz

A null-terminated ASCII string into which the Windows Sockets DLL 
copies a description of the Windows Sockets implementation. The 
text (up to 256 characters in length) may contain any characters 
except control and formatting characters: the most likely use that 
an application will put this to is to display it (possibly truncated) 
in a status message.

szSystemStatus

A null-terminated ASCII string into which the Windows Sockets DLL 
copies relevant status or configuration information. The Windows 
Sockets DLL should use this field only if the information might 
be useful to the user or support staff: it should not be considered 
as an extension of the szDescription field.

iMaxSockets

This field is retained for backward compatibility, but should be 
ignored for version 2 and later as no single value can be appropriate 
for all underlying service providers.

iMaxUdpDg

This value should be ignored for version 2 and onward. It is retained 
for compatibility with Windows Sockets specification 1.1, but should 
not be used when developing new applications. For the actual maximum 
message size specific to a particular Windows Sockets service provider 
and socket type, applications should use getsockopt to retrieve the 
value of option SO_MAX_MSG_SIZE after a socket has been created.

lpVendorInfo

This value should be ignored for version 2 and onward. It is retained 
for compatibility with Windows Sockets specification 1.1. Applications 
needing to access vendor-specific configuration information should use 
getsockopt to retrieve the value of option PVD_CONFIG. The definition 
of this value (if utilized) is beyond the scope of this specification.

Note that an application should ignore the iMaxsockets, iMaxUdpDg, and 
lpVendorInfo fields in WSAData if the value in wVersion after a successful 
call to WSAStartup is at least 2. This is because the architecture of 
Windows Sockets has been changed in version 2 to support multiple 
providers, and WSAData no longer applies to a single vendors stack. 
Two new socket options are introduced to supply provider-specific 
information: SO_MAX_MSG_SIZE (replaces the iMaxUdpDg element) and 
PVD_CONFIG (allows any other provider-specific configuration to occur).

An application or DLL may call WSAStartup more than once if it needs 
to obtain the WSAData structure information more than once. On each 
such call the application may specify any version number supported 
by the DLL.

There must be one WSACleanup call corresponding to every successful 
WSAStartup call to allow third-party DLLs to make use of a Windows 
Sockets DLL on behalf of an application. This means, for example, 
that if an application calls WSAStartup three times, it must call 
WSACleanup three times. The first two calls to WSACleanup do 
nothing except decrement an internal counter; the final WSACleanup 
call for the task does all necessary resource deallocation for the task.

Return Values

WSAStartup returns zero if successful. Otherwise, it returns one 
of the error codes listed below. Note that the normal mechanism 
whereby the application calls WSAGetLastError to determine the 
error code cannot be used, since the Windows Sockets DLL may not 
have established the client data area where the "last error" 
information is stored.

Error Codes

WSASYSNOTREADY	Indicates that the underlying network subsystem 
is not ready for network communication.
WSAVERNOTSUPPORTED	The version of Windows Sockets support 
requested is not provided by this particular Windows Sockets
implementation.
WSAEINPROGRESS	A blocking Windows Sockets 1.1 operation is 
in progress.
WSAEPROCLIM	Limit on the number of tasks supported by the Windows 
Sockets implementation has been reached.
WSAEFAULT	The lpWSAData is not a valid pointer.



           ***************************
           ***************************
			WSACleanup

The Windows Sockets WSACleanup function terminates use of the 
Windows Sockets DLL.

int  WSACleanup (void);

Remarks

An application or DLL is required to perform a successful 
WSAStartup call before it can use Windows Sockets services. 
When it has completed the use of Windows Sockets, the application 
or DLL must call WSACleanup to deregister itself from a Windows 
Sockets implementation and allow the implementation to free any 
resources allocated on behalf of the application or DLL. Any pending 
blocking or asynchronous calls issued by any thread in this process 
are canceled without posting any notification messages, or signaling 
any event objects. Any pending overlapped send and receive 
operations (WSASend/WSASendTo/WSARecv/WSARecvFrom with an overlapped 
socket) issued by any thread in this process are also canceled without 
setting the event object or invoking the completion routine, if 
specified. In this case, the pending overlapped operations fail with 
the error status WSA_OPERATION_ABORTED. Any sockets open when WSACleanup 
is called are reset and automatically deallocated as if closesocket was 
called; sockets which have been closed with closesocket but which still 
have pending data to be sent may be affectedthe pending data may be lost 
if the Windows Sockets DLL is unloaded from memory as the application 
exits. To insure that all pending data is sent an application should 
use shutdown to close the connection, then wait until the close completes 
before calling closesocket and WSACleanup. All resources and internal 
state, such as queued un-posted messages, must be deallocated so as to 
be available to the next user.

There must be a call to WSACleanup for every successful call to 
WSAStartup made by a task. Only the final WSACleanup for that task 
does the actual cleanup; the preceding calls simply decrement an 
internal reference count in the Windows Sockets DLL.

Return Values

The return value is zero if the operation was successful. Otherwise, 
the value SOCKET_ERROR is returned, and a specific error number may 
be retrieved by calling WSAGetLastError.

Comments

Attempting to call WSACleanup from within a blocking hook and then failing 
to check the return code is a common Windows Sockets programming error. 
If an application needs to quit while a blocking call is outstanding, the 
application must first cancel the blocking call with WSACancelBlockingCall 
then issue the WSACleanup call once control has been returned to the 
application.  In a multithreaded environment, WSACleanup terminates 
Windows Sockets operations for all threads.

Error Codes

WSANOTINITIALISED	A successful WSAStartup must occur before using this function.
WSAENETDOWN	The network subsystem has failed.
WSAEINPROGRESS	A blocking Windows Sockets 1.1 call is in progress, 
or the service provider is still processing a callback function.


           ***************************
           ***************************
			gethostbyname

The Windows Sockets gethostbyname function gets host information 
corresponding to a hostname.

struct hostent FAR * gethostbyname (const char FAR * name	);	
Parameters

name

[out] A pointer to the null terminated name of the host.

Remarks

gethostbyname returns a pointer to a hostent structure. The contents 
of this structure correspond to the hostname name.

The pointer which is returned points to a structure which is allocated 
by Windows Sockets. The application must never attempt to modify this 
structure or to free any of its components. Furthermore, only one copy 
of this structure is allocated per thread, and so the application 
should copy any information which it needs before issuing any other 
Windows Sockets function calls.

gethostbyname does not resolve IP address strings passed to it. Such 
a request is treated exactly as if an unknown host name were passed. 
An application with an IP address string to resolve should use inet_addr 
to convert the string to an IP address, then gethostbyaddr to obtain 
the hostent structure.

gethostbyname will resolve the string returned by a successful call 
to gethostname.

Return Values

If no error occurs, gethostbyname returns a pointer to the hostent 
structure described above. Otherwise, it returns a NULL pointer and 
a specific error number can be retrieved by calling WSAGetLastError.


This structure is allocated by Windows Sockets. An application should 
never attempt to modify this structure or to free any of its components. 
Furthermore, only one copy of this structure is allocated per thread, 
and so the application should copy any information that it needs before 
issuing any other Windows Sockets API calls.

struct hostent {
    char FAR *       h_name;
    char FAR * FAR * h_aliases;
    short            h_addrtype;
    short            h_length;
    char FAR * FAR * h_addr_list;
};
 
Members

h_name
Official name of the host (PC).If using the DNS or similar resolution 
system, it is the Fully Qualified Domain Name (FQDN) that caused the 
server to return a reply. If using a local "hosts" file, it is the 
first entry after the IP address.

h_aliases
A NULL-terminated array of alternate names.

h_addrtype
The type of address being returned.

h_length
The length, in bytes, of each address.

h_addr_list
A NULL-terminated list of addresses for the host. Addresses are returned 
in network byte order.The macro h_addr is defined to be h_addr_list[0] 
for compatibility with older software.

Error Codes

WSANOTINITIALISED	A successful WSAStartup must occur before using 
this function.
WSAENETDOWN	The network subsystem has failed.
WSAHOST_NOT_FOUND	Authoritative Answer Host not found.
WSATRY_AGAIN	Non-Authoritative Host not found, or server f
ailure.
WSANO_RECOVERY	Nonrecoverable error occurred.
WSANO_DATA	Valid name, no data record of requested type.
WSAEINPROGRESS	A blocking Windows Sockets 1.1 call is in progress, 
or the service provider is still processing a callback function.
WSAEFAULT	The name argument is not a valid part of the user address space.
WSAEINTR	The (blocking) call was canceled through WSACancelBlockingCall.


           ***************************
           ***************************
				inet_ntoa

The Windows Sockets inet_ntoa function converts a network address 
into a string in dotted format.

char FAR * inet_ntoa (struct in_addr in	);	
Parameters

in

[in] A structure which represents an Internet host address.

Remarks

This function takes an Internet address structure specified by 
the in parameter. It returns an ASCII string representing the 
address in ".'' notation as "a.b.c.d''. Note that the string 
returned by inet_ntoa resides in memory which is allocated by 
Windows Sockets. The application should not make any assumptions 
about the way in which the memory is allocated. The data is 
guaranteed to be valid until the next Windows Sockets function 
call within the same thread, but no longer.

Return Values

If no error occurs, inet_ntoa returns a char pointer to a static 
buffer containing the text address in standard ".'' notation. 
Otherwise, it returns NULL. The data should be copied before 
another Windows Sockets call is made.


           ***************************
           ***************************

				RtlMoveMemory

RtlMoveMemory moves memory either forward or backward, aligned or 
unaligned, in 4-byte blocks, followed by any remaining bytes.

VOID 
  RtlMoveMemory(
    IN VOID UNALIGNED  *Destination,
    IN CONST VOID UNALIGNED  *Source,
    IN SIZE_T  Length
    );
Parameters
Destination 
Points to the destination of the move. 

Source 
Points to the memory to be copied. 

Length 
Specifies the number of bytes to be copied. 


Comments
The (Source + Length) can overlap the Destination range passed in to 
RtlMoveMemory.

Callers of RtlMoveMemory can be running at any IRQL if both memory 
blocks are resident. Otherwise, the caller must be running at 
IRQL < DISPATCH_LEVEL.


---------------------------------------------------------
---------------------------------------------------------
SUBMISSIONS

The Liberty BASIC Newsletter encourages all LB programmers
to submit articles for publication.  Everyone has something
valuable to say, from beginners to veteran LBers.  Consider
sharing a code routine, with explanation.  Perhaps you can
review a favorite LB website, or program, or coding tool?
Why not submit a list of questions that have been nagging
at you?  How about sharing your favorite algorithm?

Send submissions to alycewatson@charter.net

---------------------------------------------------------
---------------------------------------------------------
VOLUNTEER TO PUBLISH THE LB NEWSLETTER

from Alyce:

I enjoy publishing the newsletter, but I've had a long run
of it, and I will be happy to hand over the reins of the 
Liberty BASIC Newsletter to any kind volunteer who would 
like to take over, at any time.

Requirements:
	must be over 18 years of age
	must be willing to publish one newsletter per month
	must be prepared to write the newsletter.
		(although contributions are encouraged, they
		  cannot be relied upon)

Articles can be anything of interest to LB programmers -
coding routines, explanations of LB commands, news about
LB, or the LB community, spotlight on programmers, websites,
programs written in LB, or coding tools.

The publisher may include code and information published in the
various LB forums, but only with permission of the authors
of the messages.

To volunteer, send a message to Alyce:
mailto:alycewatson@charter.net
or Carl Gundel,
mailto:carlg@libertybasic.com


---------------------------------------------------------
---------------------------------------------------------
    Comments, requests, submissions or corrections: 
            Simply reply to this message!

			The Team:
Alyce Watson, Publisher and Editor: alycewatson@charter.net
Carl Gundel, Author of Liberty BASIC: carlg@libertybasic.com
Bill Jennings, Contents and Indexes: bbjen@bigfoot.com
---------------------------------------------------------