Visual Basic Code of the Week (COTW)
http://www.codeoftheweek.com
Issue #28
All content and source code is Copyright (c) 1998 by C&D Programming Corp. No part of this issue can be reprinted or distributed in any manner without express written permission of C&D Programming Corp.

NEW! Online Catalog now available!

We have entered a partnership with VBXtras to provide many development tools available for sale on our web site. For a limited time we are offering a FREE one year subscription for anyone who purchases any products through our web site. If you are currently shopping for some cool tools, check out http://www.codeoftheweek.com/catalog.html

This area is new and does not yet have all products online. If there is something particular you are looking for (and can't find it on our site), please let us know. We probably can get it for you at a great price!

Advertising

If you are interested in advertising in COTW please email us at sponsor@codeoftheweek.com Our rates are VERY reasonable, actually they are almost FREE. We reach over three thousand Visual Basic developers each week.


Requirements for this Issue

The source code in this issue is designed for Visual Basic 5.0 and higher. It will probably work in VB4 32-bit with some minor changes.

In this Issue

This issue adds to the class module we introduced last week for manipulating network connections and retrieving the login name. This issue shows how to manually connect or disconnect from network resources. We have also included some better error handling that will complement the error handling found in the issue from last week.

cNetworkInterface Class

Description

You might have seen the dialogs built into Windows 95/NT for making and removing network connections. This class makes the necessary calls to the Networking API to show those dialogs. These functions will only work under Windows 95 and Windows NT. They depend on a DLL called MPR.DLL which should exists on all 95/NT systems that have networking installed. To connect to network resources we use the API function WNetAddConnection. To disconnect from network resources we use the API function WNetCancelConnection.

Declaration

Public Function ConnectResource(sLocalName As String, sRemoteName As String, sPassword As String)
Public Function DisconnectResource(sLocalName As String, Optional bForce As Boolean = False)

Parameters

Returns

Nothing is returned upon a successful call. If an error occurs it is raised to the caller.

Sample Usage

A couple of examples are shown below.

    Dim Network as New cNetworkInterface

    Network.ConnectResource "T:", "\\P120\APPS2", ""
    Network.DisconnectResource "T:"
    Network.ConnectResource "LPT2:", "\\P120\HP4L", "pass"
    Network.DisconnectResource "LPT2:"

The first connect will connect the T: drive to the network resource called \\P120\APPS2. The second connect will connect the LPT2 port to the network printer called \\P120\HP4L using the password "pass"

Source Code

Just paste this code into any class module and change the name of the module to cNetworkInterface.

'----------------------------------------------------------------------
'
'   Module Name:    cNetworkInterface
'   Written By:     C&D Programming Corp.
'   Create Date:    2/98
'   Copyright:      Copyright 1998 by C&D Programming Corp.  Source
'                   code may not be reproduced except for use in a
'                   compiled executable.  All rights reserved.  If
'                   you would like to reprint any or all of this
'                   code please email us at info@codeoftheweek.com
'----------------------------------------------------------------------
Option Explicit

'
'   Maximum length of a network path allowed in several of the
'   networking API calls
'
Private Const MAX_PATH = 260

'
'   Other Error Codes
'
Private Const WN_SUCCESS = 0&
Private Const ERROR_INVALID_PASSWORD = 86&
Private Const ERROR_NOT_ENOUGH_MEMORY = 8&
Private Const ERROR_INVALID_PARAMETER = 87&
Private Const ERROR_NO_MORE_ITEMS = 259&

Private Const ERROR_NOT_SUPPORTED = 50&
Private Const ERROR_REM_NOT_LIST = 51&
Private Const ERROR_DUP_NAME = 52&
Private Const ERROR_BAD_NETPATH = 53&
Private Const ERROR_NETWORK_BUSY = 54&
Private Const ERROR_DEV_NOT_EXIST = 55 '  dderror
Private Const ERROR_TOO_MANY_CMDS = 56&
Private Const ERROR_ADAP_HDW_ERR = 57&
Private Const ERROR_BAD_NET_RESP = 58&
Private Const ERROR_UNEXP_NET_ERR = 59&
Private Const ERROR_BAD_REM_ADAP = 60&
Private Const ERROR_PRINTQ_FULL = 61&
Private Const ERROR_NO_SPOOL_SPACE = 62&
Private Const ERROR_PRINT_CANCELLED = 63&
Private Const ERROR_NETNAME_DELETED = 64&
Private Const ERROR_NETWORK_ACCESS_DENIED = 65&
Private Const ERROR_BAD_DEV_TYPE = 66&
Private Const ERROR_BAD_NET_NAME = 67&
Private Const ERROR_TOO_MANY_NAMES = 68&
Private Const ERROR_TOO_MANY_SESS = 69&
Private Const ERROR_SHARING_PAUSED = 70&
Private Const ERROR_REQ_NOT_ACCEP = 71&
Private Const ERROR_REDIR_PAUSED = 72&

'
'  Winnet32 Status Codes
'
Private Const ERROR_BAD_USERNAME = 2202&
Private Const ERROR_NOT_CONNECTED = 2250&
Private Const ERROR_OPEN_FILES = 2401&
Private Const ERROR_DEVICE_IN_USE = 2404&
Private Const ERROR_BAD_DEVICE = 1200&
Private Const ERROR_CONNECTION_UNAVAIL = 1201&
Private Const ERROR_DEVICE_ALREADY_REMEMBERED = 1202&
Private Const ERROR_NO_NET_OR_BAD_PATH = 1203&
Private Const ERROR_BAD_PROVIDER = 1204&
Private Const ERROR_CANNOT_OPEN_PROFILE = 1205&
Private Const ERROR_BAD_PROFILE = 1206&
Private Const ERROR_NOT_CONTAINER = 1207&
Private Const ERROR_EXTENDED_ERROR = 1208&
Private Const ERROR_INVALID_GROUPNAME = 1209&
Private Const ERROR_INVALID_COMPUTERNAME = 1210&
Private Const ERROR_INVALID_EVENTNAME = 1211&
Private Const ERROR_INVALID_DOMAINNAME = 1212&
Private Const ERROR_INVALID_SERVICENAME = 1213&
Private Const ERROR_INVALID_NETNAME = 1214&
Private Const ERROR_INVALID_SHARENAME = 1215&
Private Const ERROR_INVALID_PASSWORDNAME = 1216&
Private Const ERROR_INVALID_MESSAGENAME = 1217&
Private Const ERROR_INVALID_MESSAGEDEST = 1218&
Private Const ERROR_SESSION_CREDENTIAL_CONFLICT = 1219&
Private Const ERROR_REMOTE_SESSION_LIMIT_EXCEEDED = 1220&
Private Const ERROR_DUP_DOMAINNAME = 1221&
Private Const ERROR_NO_NETWORK = 1222&
Private Const ERROR_CANCELLED = 1223
Private Const ERROR_USER_MAPPED_FILE = 1224
Private Const ERROR_CONNECTION_REFUSED = 1225
Private Const ERROR_GRACEFUL_DISCONNECT = 1226
Private Const ERROR_ADDRESS_ALREADY_ASSOCIATED = 1227
Private Const ERROR_ADDRESS_NOT_ASSOCIATED = 1228
Private Const ERROR_CONNECTION_INVALID = 1229
Private Const ERROR_CONNECTION_ACTIVE = 1230
Private Const ERROR_NETWORK_UNREACHABLE = 1231
Private Const ERROR_HOST_UNREACHABLE = 1232
Private Const ERROR_PROTOCOL_UNREACHABLE = 1233
Private Const ERROR_PORT_UNREACHABLE = 1234
Private Const ERROR_REQUEST_ABORTED = 1235
Private Const ERROR_CONNECTION_ABORTED = 1236
Private Const ERROR_RETRY = 1237
Private Const ERROR_CONNECTION_COUNT_LIMIT = 1238
Private Const ERROR_LOGIN_TIME_RESTRICTION = 1239
Private Const ERROR_LOGIN_WKSTA_RESTRICTION = 1240
Private Const ERROR_INCORRECT_ADDRESS = 1241
Private Const ERROR_ALREADY_REGISTERED = 1242
Private Const ERROR_SERVICE_NOT_FOUND = 1243
Private Const ERROR_NOT_AUTHENTICATED = 1244
Private Const ERROR_NOT_LOGGED_ON = 1245
Private Const ERROR_CONTINUE = 1246
Private Const ERROR_ALREADY_INITIALIZED = 1247
Private Const ERROR_NO_MORE_DEVICES = 1248
Private Const ERROR_NO_SUCH_SITE = 1249
Private Const ERROR_DOMAIN_CONTROLLER_EXISTS = 1250
Private Const ERROR_DS_NOT_INSTALLED = 1251

'
' Error retrieval function for the network library API
'
Private Declare Function WNetGetLastError Lib "mpr.dll" _
    Alias "WNetGetLastErrorA" _
    (lpError As Long, ByVal lpErrorBuf As String, _
    ByVal nErrorBufSize As Long, ByVal lpNameBuf As String, _
    ByVal nNameBufSize As Long) As Long

'
'   Simple Network Resource connection and disconnection API calls.
'
Private Declare Function WNetAddConnection Lib "mpr.dll" Alias "WNetAddConnectionA" _
    (ByVal lpszNetPath As String, ByVal lpszPassword As String, _
    ByVal lpszLocalName As String) As Long
Private Declare Function WNetCancelConnection Lib "mpr.dll" Alias "WNetCancelConnectionA" _
    (ByVal lpszName As String, ByVal bForce As Long) As Long

Public Function ConnectResource(sLocalName As String, sRemoteName As String, _
                                sPassword As String)
    Dim lReturnVal As Long

    lReturnVal = WNetAddConnection(sRemoteName, sPassword & vbNullChar, _
                                    sLocalName & vbNullChar)
    If lReturnVal <> WN_SUCCESS Then
        Err.Raise lReturnVal, "cNetworkInterface.ConnectResource", WNetErrorDescription(lReturnVal)
        Exit Function
    End If
End Function

Public Function DisconnectResource(sLocalName As String, Optional bForce As Boolean = False)
    Dim lReturnVal As Long

    lReturnVal = WNetCancelConnection(sLocalName, bForce)
    If lReturnVal <> WN_SUCCESS Then
        Err.Raise lReturnVal, "cNetworkInterface.DisconnectResource", WNetErrorDescription(lReturnVal)
        Exit Function
    End If
End Function

'
'   When calling API functions, the strings returned often have a Null
'   (or vbNullChar, which is the VB shortcut) character at the end of the
'   string.  This function removes the Null character.
'
Private Function RemoveNull(sData As String) As String
    Dim iNullPos As Integer

    iNullPos = InStr(sData, vbNullChar)
    If iNullPos <> 0 Then
        RemoveNull = Left(sData, iNullPos - 1)
    Else
        RemoveNull = sData
    End If
End Function

Public Function WNetErrorDescription(lError As Long)
    Dim sMsg As String

    Select Case lError
        '
        ' 32-Bit Networking Error Codes
        '
        Case ERROR_EXTENDED_ERROR
            sMsg = "An extended error has occurred. " & WNetExtendedError(lError)
        Case ERROR_BAD_USERNAME
            sMsg = "The specified username is invalid."
        Case ERROR_NOT_CONNECTED
            sMsg = "This network connection does not exist."
        Case ERROR_OPEN_FILES
            sMsg = "This network connection has files open or requests pending."
        Case ERROR_DEVICE_IN_USE
            sMsg = "The device is in use by an active process and cannot be disconnected."
        Case ERROR_BAD_DEVICE
            sMsg = "The specified device name is invalid."
        Case ERROR_CONNECTION_UNAVAIL
            sMsg = "The device is not currently connected but it is a remembered connection."
        Case ERROR_DEVICE_ALREADY_REMEMBERED
            sMsg = "An attempt was made to remember a device that had previously been remembered."
        Case ERROR_NO_NET_OR_BAD_PATH
            sMsg = "No network provider accepted the given network path."
        Case ERROR_BAD_PROVIDER
            sMsg = "The specified network provider name is invalid."
        Case ERROR_CANNOT_OPEN_PROFILE
            sMsg = "Unable to open the network connection profile."
        Case ERROR_BAD_PROFILE
            sMsg = "The network connection profile is corrupt."
        Case ERROR_NOT_CONTAINER
            sMsg = "Cannot enumerate a non-container."
        Case ERROR_INVALID_GROUPNAME
            sMsg = "The format of the specified group name is invalid."
        Case ERROR_INVALID_COMPUTERNAME
            sMsg = "The format of the specified computer name is invalid."
        Case ERROR_INVALID_EVENTNAME
            sMsg = "The format of the specified event name is invalid."
        Case ERROR_INVALID_DOMAINNAME
            sMsg = "The format of the specified domain name is invalid."
        Case ERROR_INVALID_SERVICENAME
            sMsg = "The format of the specified service name is invalid."
        Case ERROR_INVALID_NETNAME
            sMsg = "The format of the specified network name is invalid."
        Case ERROR_INVALID_SHARENAME
            sMsg = "The format of the specified share name is invalid."
        Case ERROR_INVALID_PASSWORDNAME
            sMsg = "The format of the specified password is invalid."
        Case ERROR_INVALID_MESSAGENAME
            sMsg = "The format of the specified message name is invalid."
        Case ERROR_INVALID_MESSAGEDEST
            sMsg = "The format of the specified message destination is invalid."
        Case ERROR_SESSION_CREDENTIAL_CONFLICT
            sMsg = "The credentials supplied conflict with an existing set of credentials."
        Case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
            sMsg = "An attempt was made to establish a session to a Lan Manager server, but there are already too many sessions established to that server."
        Case ERROR_DUP_DOMAINNAME
            sMsg = "The workgroup or domain name is already in use by another computer on the network."
        Case ERROR_NO_NETWORK
            sMsg = "The network is not present or not started."
        Case ERROR_CANCELLED
            sMsg = "The operation was canceled by the user."
        Case ERROR_USER_MAPPED_FILE
            sMsg = "The requested operation cannot be performed on a file with a user-mapped section open."
        Case ERROR_CONNECTION_REFUSED
            sMsg = "The remote system refused the network connection."
        Case ERROR_GRACEFUL_DISCONNECT
            sMsg = "The network connection was gracefully closed."
        Case ERROR_ADDRESS_ALREADY_ASSOCIATED
            sMsg = "The network transport endpoint already has an address associated with it."
        Case ERROR_ADDRESS_NOT_ASSOCIATED
            sMsg = "An address has not yet been associated with the network endpoint."
        Case ERROR_CONNECTION_INVALID
            sMsg = "An operation was attempted on a nonexistent network connection."
        Case ERROR_CONNECTION_ACTIVE
            sMsg = "An invalid operation was attempted on an active network connection."
        Case ERROR_NETWORK_UNREACHABLE
            sMsg = "The remote network is not reachable by the transport."
        Case ERROR_HOST_UNREACHABLE
            sMsg = "The remote system is not reachable by the transport."
        Case ERROR_PROTOCOL_UNREACHABLE
            sMsg = "The remote system does not support the transport protocol."
        Case ERROR_PORT_UNREACHABLE
            sMsg = "No service is operating at the destination network endpoint on the remote system."
        Case ERROR_REQUEST_ABORTED
            sMsg = "The request was aborted."
        Case ERROR_CONNECTION_ABORTED
            sMsg = "The network connection was aborted by the local system."
        Case ERROR_RETRY
            sMsg = "The operation could not be completed. A retry should be performed."
        Case ERROR_CONNECTION_COUNT_LIMIT
            sMsg = "A connection to the server could not be made because the limit on the number of concurrent connections for this account has been reached."
        Case ERROR_LOGIN_TIME_RESTRICTION
            sMsg = "Attempting to log in during an unauthorized time of day for this account."
        Case ERROR_LOGIN_WKSTA_RESTRICTION
            sMsg = "The account is not authorized to log in from this station."
        Case ERROR_INCORRECT_ADDRESS
            sMsg = "The network address could not be used for the operation requested."
        Case ERROR_ALREADY_REGISTERED
            sMsg = "The service is already registered."
        Case ERROR_SERVICE_NOT_FOUND
            sMsg = "The specified service does not exist."
        Case ERROR_NOT_AUTHENTICATED
            sMsg = "The operation being requested was not performed because the user has not been authenticated."
        Case ERROR_NOT_LOGGED_ON
            sMsg = "The operation being requested was not performed because the user has not logged on to the network. The specified service does not exist."
        Case ERROR_CONTINUE
            sMsg = "Continue with work in progress."
        Case ERROR_ALREADY_INITIALIZED
            sMsg = "An attempt was made to perform an initialization operation when initialization has already been completed."
        Case ERROR_NO_MORE_DEVICES
            sMsg = "No more local devices."
        Case ERROR_NO_SUCH_SITE
            sMsg = "The specified site does not exist."
        Case ERROR_DOMAIN_CONTROLLER_EXISTS
            sMsg = "A domain controller with the specified name already exists."
        Case ERROR_DS_NOT_INSTALLED
            sMsg = "An error occurred while installing the Windows NT directory service. Please view the event log for more information."

        '
        ' Non 32-Bit Error Codes
        '
        Case ERROR_INVALID_PASSWORD '  = 86&
            sMsg = "Invalid password to access resource"
        Case ERROR_NOT_ENOUGH_MEMORY ' = 8&
            sMsg = "Not enough memory to process the request"
        Case ERROR_INVALID_PARAMETER ' = 87&
            sMsg = "Invalid parameter"
        Case ERROR_NO_MORE_ITEMS ' = 259&
            sMsg = "No more items available"
        Case ERROR_NOT_SUPPORTED ' 50&
            sMsg = "The network request is not supported."
        Case ERROR_REM_NOT_LIST ' 51&
            sMsg = "The remote computer is not available."
        Case ERROR_DUP_NAME ' 52&
            sMsg = "A duplicate name exists on the network."
        Case ERROR_BAD_NETPATH ' 53&
            sMsg = "The network path was not found."
        Case ERROR_NETWORK_BUSY ' 54&
            sMsg = "The network is busy."
        Case ERROR_DEV_NOT_EXIST ' 55 '  dderror
            sMsg = "The specified network resource or device is no longer available."
        Case ERROR_TOO_MANY_CMDS ' 56&
            sMsg = "The network BIOS command limit has been reached."
        Case ERROR_ADAP_HDW_ERR ' 57&
            sMsg = "A network adapter hardware error occurred."
        Case ERROR_BAD_NET_RESP ' 58&
            sMsg = "The specified server cannot perform the requested operation."
        Case ERROR_UNEXP_NET_ERR ' 59&
            sMsg = "An unexpected network error occurred."
        Case ERROR_BAD_REM_ADAP ' 60&
            sMsg = "The remote adapter is not compatible."
        Case ERROR_PRINTQ_FULL ' 61&
            sMsg = "The printer queue is full."
        Case ERROR_NO_SPOOL_SPACE ' 62&
            sMsg = "Space to store the file waiting to be printed is not available on the server."
        Case ERROR_PRINT_CANCELLED ' 63&
            sMsg = "Your file waiting to be printed was deleted."
        Case ERROR_NETNAME_DELETED ' 64&
            sMsg = "The specified network name is no longer available."
        Case ERROR_NETWORK_ACCESS_DENIED ' 65&
            sMsg = "Network access is denied."
        Case ERROR_BAD_DEV_TYPE ' 66&
            sMsg = "The network resource type is not correct."
        Case ERROR_BAD_NET_NAME ' 67&
            sMsg = "The network name cannot be found."
        Case ERROR_TOO_MANY_NAMES ' 68&
            sMsg = "The name limit for the local computer network adapter card was exceeded."
        Case ERROR_TOO_MANY_SESS ' 69&
            sMsg = "The network BIOS session limit was exceeded."
        Case ERROR_SHARING_PAUSED ' 70&
            sMsg = "The remote server has been paused or is in the process of being started."
        Case ERROR_REQ_NOT_ACCEP ' 71&
            sMsg = "The network request was not accepted."
        Case ERROR_REDIR_PAUSED ' 72&
            sMsg = "The specified printer or disk device has been paused."
        Case Else
            sMsg = "Error " & lError & " occurred.  No description defined for this error code."
    End Select
    WNetErrorDescription = sMsg
End Function

Public Function WNetExtendedError(lError As Long) As String
    Dim lRet As Long
    Dim lErrorBuf As Long
    Dim sErrorBuf As String
    Dim lNameBuf As Long
    Dim sNameBuf As String

    ' This should work in Windows 95 or NT
    sErrorBuf = Space(256)
    lErrorBuf = Len(sErrorBuf)
    sNameBuf = Space(256)
    lNameBuf = Len(sNameBuf)

    lRet = WNetGetLastError(lError, sErrorBuf, lErrorBuf, sNameBuf, lNameBuf)
    ' for now, just return the error text
    WNetExtendedError = RemoveNull(sErrorBuf)
End Function

NEW! Online Catalog now available!

We have entered a partnership with VBXtras to provide many development tools available for sale on our web site. For a limited time we are offering a FREE one year subscription for anyone who purchases any products through our web site. If you are currently shopping for some cool tools, check out http://www.codeoftheweek.com/catalog.html

This area is new and does not yet have all products online. If there is something particular you are looking for (and can't find it on our site), please let us know. We probably can get it for you at a great price!

This document is available on the web

Paid subscribers can view this issue in HTML format. There is no additional source or information in the HTML formatted document. It just looks a little better since we have included some HTML formatting. Just point your browser to http://www.codeoftheweek.com/membersonly/bi/0028.html

Summary

That concludes this issue of COTW. We hope you find the source code useful in your development.

The below describes the ways you can supply us some feedback about COTW. We would like to see our members help mold COTW into the best Visual Basic source code resource available. But to do that we need your feedback about what you like and what you do not like about COTW.

Advertising

If you are interested in advertising in COTW please email us at sponsor@codeoftheweek.com Our rates are VERY reasonable, actually they are almost FREE. We reach over three thousand Visual Basic developers each week.

How to tell us what you think

If you have any suggestions for topics you would like to see covered or questions about this issue, please email them to info@codeoftheweek.com or use online feedback form at http://www.codeoftheweek.com/feedback.html.

If you have any source code you would like to submit for possible inclusion in COTW, please fill out our online submission form at http://www.codeoftheweek.com/submission.html.

Contact Information

C&D Programming Corp.
PO Box 20128
Floral Park, NY 11002-0128
Phone or Fax: (212) 504-7945
Email: info@codeoftheweek.com
Web: http://www.codeoftheweek.com

Subscription Update

Thank you for trying Code of the Week for Visual Basic.

Your free trial expires after you receive your fourth issue. If you want to continue to receive Code of the Week you can get 52 issues of COTW for only $19.95. This is a full year of Visual Basic source code and information to help with all your development. So don't wait, subscribe now! The quickest way to subscribe is to jump to our online order form at http://www.codeoftheweek.com/order.html