Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid handle while trying to connect to networkshare

I have a program which needs to put data on a network share. In some cases, the user has no access through his account, and would need to provide credentials to login.

My idea was to have the program popup the windows credential screen so the user can login (like when the user would open the share through windows explorer).

I found the WNetUseConnection API which would allow to login to the share without mapping it, and it has options to give a prompt.

This is the code I'm using:

Public Class frmMain

    Private Const CONNECT_INTRERACTIVE = &H8
    Private Const CONNECT_PROMPT = &H10
    Private Const RESOURCETYPE_DISK = &H1

    Private Structure NETRESOURCE
        Public dwScope As Long
        Public dwType As Long
        Public dwDisplayType As Long
        Public dwUsage As Long
        Public lpLocalName As String
        Public lpRemoteName As String
        Public lpComment As String
        Public lpProvider As String
    End Structure

    Private Declare Function WNetUseConnection Lib "mpr.dll" _
        Alias "WNetUseConnectionA" ( _
        ByVal hwndOwner As Long, _
        ByRef lpNetResource As NETRESOURCE, _
        ByVal lpUsername As String, _
        ByVal lpPassword As String, _
        ByVal dwFlags As Long, _
        ByVal lpAccessName As String, _
        ByRef lpBufferSize As Long, _
        ByRef lpResult As Long) _
   As Long

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim resource As New NETRESOURCE
        Dim success As Long
        Dim ErrInfo As Long

        With resource
            .dwType = RESOURCETYPE_DISK
            .lpLocalName = vbNullString
            .lpRemoteName = "\\server\folder\"
            .lpProvider = vbNullString
        End With

        ErrInfo = WNetUseConnection(Me.Handle, resource, "", "", CONNECT_INTRERACTIVE Or CONNECT_PROMPT, vbNull, vbNull, success)

        Console.WriteLine(ErrInfo)

        Dim errorMessage As String
        errorMessage = New Win32Exception().Message

        Console.WriteLine(errorMessage)
End Sub

The error I'm getting back is:

The handle is invalid (code 2091649073639).

Is there a way to get this working?

like image 490
Ikke Avatar asked Nov 08 '13 13:11

Ikke


People also ask

How do I fix error The handle is invalid?

"The handle is invalid" error can appear when you are logging in, and the problem is usually related to a Windows Update problem or using the wrong credentials to log in. Rebooting your computer should allow Windows Updates to continue if that's the issue.

Can not connect to network share?

Select Network and Sharing Center.Go to Change advanced sharing settings. After that, expand All networks. Locate the Public folder sharing option and make sure it's checked. Then restart your computer.

What does handle is invalid mean?

The Handle is Invalid. This error message basically means that the affected user cannot get into their user account and, by extension, their computer, and that is most definitely a significant problem. Thankfully, there exist ways that can be used to try and fix this problem.


1 Answers

There seem to be several issues with the code you posted:

  1. Your P/Invoke types need to be tweaked. Here are the native Windows types and their appropriate VB .Net counterparts:

    • HWND -> IntPtr
    • LPDWORD -> IntPtr
    • DWORD -> UInt32 (I've also seen Integer used)

    Using IntPtr allows the runtime to use a 32-bit or 64-bit pointer, depending on the machine architecture. DWORDs are always 32 bit, even on a 64-bit machine. See also: Visual C++: How large is a DWORD with 32- and 64-bit code?

  2. The P/Invoke Signature has the username and password parameters reversed. The password parameter should actually be first. It doesn't matter in your case because the user gets prompted for this information. However, it might matter when you try to pass those values in later...

  3. The remote share should not have the trailing backslash

    .lpRemoteName = "\\server\folder\"

    should be

    .lpRemoteName = "\\server\folder"

  4. Finally, I had to add the buffer parameter to get the code to work. Without it, the WNetUseConnection function always returned ERROR_MORE_DATA, which means the buffer is too small.

Here is the complete code I used (tested on Windows 8 64-bit, Windows 7 32-bit):

Imports System.ComponentModel
Imports System.Text

Public Class frmMain
    Private Const CONNECT_INTRERACTIVE = &H8
    Private Const CONNECT_PROMPT = &H10
    Private Const RESOURCETYPE_DISK = &H1

    Private Structure NETRESOURCE
        Public dwScope As UInt32
        Public dwType As UInt32
        Public dwDisplayType As UInt32
        Public dwUsage As UInt32
        Public lpLocalName As String
        Public lpRemoteName As String
        Public lpComment As String
        Public lpProvider As String
    End Structure

    Private Declare Function WNetUseConnection Lib "mpr.dll" _
        Alias "WNetUseConnectionA" ( _
        ByVal hwndOwner As IntPtr, _
        ByRef lpNetResource As NETRESOURCE, _
        ByVal lpPassword As String, _
        ByVal lpUsername As String, _
        ByVal dwFlags As UInt32, _
        ByVal lpAccessName As StringBuilder, _
        ByRef lpBufferSize As IntPtr, _
        ByRef lpResult As IntPtr) _
   As UInt32

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim resource As New NETRESOURCE
        Dim success As Long
        Dim ErrInfo As Long
        Const BUFFERSIZE As Integer = 1024
        Dim buffer As New StringBuilder(BUFFERSIZE)

        With resource
            .dwType = RESOURCETYPE_DISK
            .lpLocalName = vbNullString
            .lpRemoteName = "\\server\folder"
            .lpProvider = vbNullString
        End With

        ErrInfo = WNetUseConnection(Me.Handle, resource, "", "", CONNECT_INTRERACTIVE Or CONNECT_PROMPT, buffer, BUFFERSIZE, success)

        If ErrInfo > 0 Then
            Dim winExcept As New Win32Exception()
            LogMsg(winExcept.Message)
        Else
            LogMsg("all good")
        End If

    End Sub

    Private Sub LogMsg(ByVal msg As String)
        System.Diagnostics.Debug.WriteLine(msg)
        MsgBox(msg)
    End Sub

End Class
like image 198
chue x Avatar answered Oct 13 '22 12:10

chue x