(c) 2002 Visual Studio Magazine 
Fawcette Technical Publications

Issue: May 2002
Section: Access Windows Networking Info
Author: L.J. Johnson

VB6	Trace Code Execution in the DLL
Listing 1	This code enables you to trace the execution of the code in the DLL when the user presses the <Add Connect3> button in the UI. It includes the critical code in Class_Initialize to check for the version of the operating system that's running. Knowing the type of OS allows the code to add the correct late-bound class later.

 [In cNetCalls]
Private Sub Class_Initialize()
Dim p_objGetOS As cOsVersion
Set p_objGetOS = New cOsVersion
m_enmOsType = p_objGetOS.TypeValidOS
Select Case m_enmOsType
	Case Valid_Win95, Valid_Win98, Valid_WinME
		Set objNetCalls = New cNet_Win9x
	Case Valid_NT_Pre40, Valid_NT40, Valid_W2K, _
		Valid_XP
		Set objNetCalls = New cNet_NT
End Select
End Sub

Public Sub AddConnection3(ByVal Password As _
	String, ByVal UserName As String, _
	ByVal LocalName As String, ByVal RemoteName _
	As String, ByVal HwndOwner As Long, Optional _
	ByVal Persistent As Boolean = False)
objNetCalls.AddConnection3 Password, UserName, _
	LocalName, RemoteName, HwndOwner, Persistent
End Sub

[in cNet_NT (or cNet_Win9x)]
modWNetCalls.AddConnection3 xi_strPassword, _
	xi_strUserName, xi_strLocalName, _
	xi_strRemoteName, xi_lngHwndOwner, _
	False, xi_blnPersistent

[in modWNetCalls]
Dim p_typNetRes As NETRESOURCE_STRING
p_typNetRes.dwType = enmResType.RESOURCETYPE_DISK
p_typNetRes.lpLocalName = xi_strLocalName
p_typNetRes.lpRemoteName = xi_strRemoteName
If xi_blnPersistent = True Then
	p_lngFlags = CONNECT_UPDATE_PROFILE Or _
		CONNECT_INTERACTIVE
Else
	p_lngFlags = CONNECT_INTERACTIVE
End If
p_lngRtn = WNetAddConnection3(xi_lngHwndOwner, _
	p_typNetRes, vbNullString, vbNullString, _
	p_lngFlags)
If p_lngRtn <> NO_ERROR Then
	Err.Raise p_lngRtn + cnstErrBase, _
		cnstProcName, "Descriptive text..."
End If

VB6	Work with the Net* Functions
Listing 2	This code shows the NT version of the EnumShares function. The NT version is in a private class, with its own API declarations and structures. The code calls the private class (late-bound) from the public cNetCalls wrapper class, depending on the operating system version that's running.

Option Explicit

Private Declare Function NetShareEnum Lib _
	"netapi32.dll" (ServerName As Byte, ByVal _
	level As Long, Buffer As Long, ByVal _
	PreMaxLen As Long, EntriesRead As Long, _
	TotalEntries As Long, Resume_Handle As Long) _
	As Long
Private Type SHARE_INFO_2
	shi2_netname As Long
	shi2_type As Long
	shi2_remark As Long
	shi2_permissions As Long
	shi2_max_uses As Long
	shi2_current_uses As Long
	shi2_path As Long
	shi2_passwd As Long
End Type

Private Type SHARE_INFO_1
	shi1_netname As Long
	shi1_type As Long
	shi1_remark As Long
End Type

Public Function EnumShares(ByVal _
	xi_strServerName As String) As Variant
Dim p_abytServerName() As Byte
Dim p_atypShareInfo_1() As SHARE_INFO_1
Dim p_atypShareInfo_2() As SHARE_INFO_2
xi_strServerName = PrepareServerName( _
	xi_strServerName)
p_abytServerName = xi_strServerName & vbNullChar
p_blnLevel2 = False
p_lngRtn = NetShareEnum(p_abytServerName(0), _
	2, p_lngPtrBuffer, 4096&, p_lngEntriesRead, _
	p_lngTotalEntries, p_lngResumeHwnd)
If p_lngRtn = NERR_SUCCESS Then
	p_blnLevel2 = True
Else
	p_lngRtn = NetShareEnum(p_abytServerName(0), _
		1, p_lngPtrBuffer, 4096&, _
		p_lngEntriesRead, p_lngTotalEntries, _
		p_lngResumeHwnd)
	If p_lngRtn <> NERR_SUCCESS Then
		GoTo Err_Handler
	End If
If p_lngEntriesRead < 1 Then
	GoTo Clean_Up
End If
ReDim p_vntRtn(0 To 9, 0 To (p_lngEntriesRead - _
	1)) As Variant
For p_lngLoop = 0 To p_lngEntriesRead - 1
	If p_blnLevel2 = True Then
		ReDim p_atypShareInfo_2 (0 To _
			p_lngEntriesRead _
			- 1) As SHARE_INFO_2
		CopyMem p_atypShareInfo_2(0), _
			ByVal p_lngPtrBuffer, _
			Len(p_atypShareInfo_2(0 _
			)) * p_lngEntriesRead
		With p_atypShareInfo_2(p_lngLoop)
		p_vntRtn(enmShareEnum.Netname, _
			p_lngLoop) = PointerToStringW( _
			.shi2_netname)
		p_vntRtn(enmShareEnum.MaxUses, p_lngLoop) _
			=.shi2_max_uses
		' Other arrays vars set
		End With
ElseIf p_blnLevel2 = False Then
		ReDim p_atypShareInfo_1 (0 To _
			p_lngEntriesRead - 1) As SHARE_INFO_1
		CopyMem p_atypShareInfo_1(0), ByVal _
			p_lngPtrBuffer, Len(p_atypShareInfo_1 _
			(0)) * p_lngEntriesRead
		With p_atypShareInfo_1 (p_lngLoop)
		p_vntRtn(enmShareEnum.Netname, p_lngLoop) _
			= PointerToStringW(.shi1_netname)
		' Other arrays vars set
Next p_lngLoop
EnumShares = p_vntRtn
Clean_Up:
If p_lngPtrBuffer <> 0 Then
	NetApiBufferFree _
		p_lngPtrBuffer
End If
Exit Function
Err_Handler:
	' Raise an error
End Function

VB6	View the Win98 EnumShares Function
Listing 3	This code shows the Win98 version of the EnumShares function. Like the NT version, the Win9x version is in a private class, with its own API declarations and structures. Note the differences between the Win9x and NT (in Listing 2) versions, including the API declarations and the UDTs.

Private Declare Function NetShareEnum95 Lib _
	"svrapi" Alias "NetShareEnum" (ByVal _
	lpServerName As String, ByVal dwLevel As _
	Integer, lpBuffer As Any, ByVal cbBuffer As _
	Integer, EntriesRead As Integer, _
	TotalEntries As Integer) As Long
Public Const LM20_NNLEN As Integer = 12
Public Const SHPWLEN As Integer = 8
Private Type Share_Info_1_9x
	shi1_netname(0 To LM20_NNLEN) As Byte
	shi1_pad1 As Byte
	shi1_type As Integer
	shi1_remark As Long
End Type
Private Type Share_Info_50_9x
	Netname(0 To LM20_NNLEN)            As Byte
	ShareType As Byte
	Flags As Integer
	lpRemark As Long
	lpPath As Long
	PasswordRW(0 To SHPWLEN) As Byte
	PasswordRO(0 To SHPWLEN) As Byte
End Type

Public Function EnumShares(ByVal _
	xi_strServerName As String) As Variant
Dim p_abytBuffer() As Byte
Dim p_typShareInfo_50 As Share_Info_50_9x
Dim p_typShareInfo_1 As Share_Info_1_9x
xi_strServerName = UCase$(PrepareServerName( _
	xi_strServerName))
	p_lngBufferLen = &H4000
	ReDim p_abytBuffer(0 To (p_lngBufferLen _
		- 1)) As Byte
p_blnIsLevel50 = False
p_lngRtn = NetShareEnum95(xi_strServerName, _
	50, p_abytBuffer(0), p_lngBufferLen, _
	p_intEntriesRead, p_intTotalEntries)
If p_lngRtn = NERR_SUCCESS Then
	p_blnIsLevel50 = True
Else
	p_lngRtn = NetShareEnum95 (xi_strServerName, _
		1, p_abytBuffer(0), p_lngBufferLen, _
		p_intEntriesRead, p_intTotalEntries)
	If p_lngRtn <> NERR_SUCCESS Then
		GoTo Err_Handler
	End If
End If
If p_intEntriesRead < 1 Then
	GoTo Clean_Up
End If
ReDim p_vntRtn(0 To 9, 0 To (p_intEntriesRead _
	- 1)) As Variant
p_lngOffset = 0
For p_lngLoop = 0 To (p_intEntriesRead - 1)
	If p_blnIsLevel50 = True Then
		CopyMem p_typShareInfo_50, p_abytBuffer( _
			p_lngOffset), Len(p_typShareInfo_50)
		With p_typShareInfo_50
		p_vntRtn(enmShareEnum.Netname, p_lngLoop) _
			= TrimNull(StrConv(.Netname, _
			vbUnicode))
		p_vntRtn(enmShareEnum.Remark, p_lngLoop) _
			= PointerToStringA(.lpRemark)
		p_vntRtn(enmShareEnum.MaxUses, p_lngLoop) _
			= 0
		' Other arrays vars set
		End With
		p_lngOffset = p_lngOffset + Len( _
			p_typShareInfo_50)
	Else
		CopyMem p_typShareInfo_1, p_abytBuffer( _
			p_lngOffset), Len(p_typShareInfo_1)
		With p_typShareInfo_1
		p_vntRtn(enmShareEnum.Netname, p_lngLoop) _
			= TrimNull(StrConv(.shi1_netname, _
			vbUnicode))
		p_lngOffset = p_lngOffset + _
			Len(p_typShareInfo_1)
		' Other arrays vars set
	End If
Next p_lngLoop
EnumShares = p_vntRtn
Exit Function
Err_Handler:
	' Raise an error
End Function
