Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: VB4/32,VB5,VB6
Expertise: Advanced
Jul 3, 1999

GetUNCName - Convert a file path to a UNC path

' Converts a reference to a file in the standard Windows
' format (e.g. "H:\ServerDir\Filename.ext") in the corresponding UNC
' format (e.g. "\\ServerName\ExportedDir\ServerDir\FileName.txt")
'
' It turns to be very useful when a program running on a workstation
' has to pass a file reference to another app running on another workstation
' or when the file reference should be stored in a database for use from
' every application on the network.

' Declares for querying Windows version

Const VER_PLATFORM_WIN32s = 0               'Win32s on Windows 3.1
Const VER_PLATFORM_WIN32_WINDOWS = 1        'Win32 on Windows 95
Const VER_PLATFORM_WIN32_NT = 2             'Win32 on Windows NT

Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib "Kernel32" Alias "GetVersionExA" _
    (lpVersionInformation As OSVERSIONINFO) As Long

' Declare for Registry functions

Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_PERFORMANCE_DATA = &H80000004
Const HKEY_CURRENT_CONFIG = &H80000005
Const HKEY_DYN_DATA = &H80000006

Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As _
    Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
    (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _
    ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValue Lib "advapi32.dll" Alias _
    "RegQueryValueA" (ByVal hKey As Long, ByVal lpSubKey As String, _
    ByVal lpValue As String, lpcbValue As Long) As Long

' Note that if you declare lpData as String, then it is necessary to pass it 
' with ByVal
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias _
    "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
    ByVal lpReserved As Long, lpType As Long, lpData As Any, _
    lpcbData As Long) As Long
Private Declare Function RegEnumKey Lib "advapi32.dll" Alias "RegEnumKeyA" _
    (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, _
    ByVal cbName As Long) As Long
Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" _
    (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, _
    lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, _
    ByVal lpData As String, lpcbData As Long) As Long
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" _
    (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function GetComputerName Lib "Kernel32" Alias _
    "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Private Declare Function WNetGetConnection Lib "mpr.dll" Alias _
    "WNetGetConnectionA" (ByVal lpszLocalName As String, _
    ByVal lpszRemoteName As String, cbRemoteName As Long) As Long

' This is the main function of the group

Public Function GetUNCName(pathName As String) As String

    Dim os As OSVERSIONINFO
    
    ' determine if we're running under Windows 9x or NT
    os.dwOSVersionInfoSize = Len(os)
    GetVersionEx os
    
    If (os.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS) Then
        ' runnning under Windows 9x
        GetUNCName = GetUNCName95(pathName)
    ElseIf (os.dwPlatformId = VER_PLATFORM_WIN32_NT) Then
        ' running under Windows NT
        GetUNCName = GetUNCNameNT(pathName)
    End If
        
End Function

' Private function that does the work under Windows 95

Private Function GetUNCName95(pathName As String) As String
    Dim hKey As Long
    Dim hKey2 As Long
    Dim exitFlag As Boolean
    Dim i As Double
    Dim ErrCode As Long
    Dim rootKey As String
    Dim key As String
    Dim computerName As String
    Dim lComputerName As Long
    
    ' First of all, verify whether the disk is networked
    If Mid(pathName, 2, 1) = ":" Then
        Dim UNCName As String
        Dim lenUNC As Long
        
        UNCName = String$(260, 0)
        lenUNC = 260
    
        ErrCode = WNetGetConnection(Left(pathName, 2), UNCName, lenUNC)

        If ErrCode = 0 Then
            UNCName = Trim(Left$(UNCName, InStr(UNCName, vbNullChar) - 1))
            GetUNCName95 = UNCName & Mid(pathName, 3)
            Exit Function
        End If
    End If
    
    ' else, scan the registry looking for shared resources (Win9x version)
    computerName = String$(255, 0)
    lComputerName = Len(computerName)
    ErrCode = GetComputerName(computerName, lComputerName)
    If ErrCode <> 1 Then
        GetUNCName95 = pathName
        Exit Function
    End If
    
    computerName = Trim(Left$(computerName, InStr(computerName, _
        vbNullChar) - 1))
    rootKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Network\Lanman"
    ErrCode = RegOpenKey(HKEY_LOCAL_MACHINE, rootKey, hKey)
    If ErrCode <> 0 Then
        GetUNCName95 = pathName
        Exit Function
    End If
    
    i = 0
    Do Until exitFlag
        Dim szValue As String
        Dim szValueName As String
        Dim cchValueName As Long
        Dim szResourceName As String
        Dim cchResourceName As Long
        Dim dwValueType As Long
        Dim dwValueSize As Long
        Dim exitw As Boolean
        Dim Path As String
        Dim j As Double
        
        szResourceName = String(1024, 0)
        cchResourceName = Len(szResourceName)
        
        ' loop on all shared resources
        ErrCode = RegEnumKey(hKey, i, szResourceName, cchResourceName)
                                           
        If ErrCode <> 0 Then
            exitFlag = True
        Else
            ' for each shared resource, read the value looking for PATH
            szResourceName = Trim(Left$(szResourceName, InStr(szResourceName, _
                vbNullChar) - 1))
            key = rootKey & "\" & szResourceName
            RegOpenKey HKEY_LOCAL_MACHINE, key, hKey2
            
            j = 0
            Do Until exitw
                szValue = String$(260, 0)
                dwValueSize = Len(szValue)
                szValueName = String(1024, 0)
                cchValueName = Len(szValueName)
        
                ErrCode = RegEnumValue(hKey2, j, szValueName, cchValueName, 0, _
                    dwValueType, szValue, dwValueSize)
                If ErrCode <> 0 Then
                    exitw = True
                Else
                    szValueName = Trim(Left$(szValueName, InStr(szValueName, _
                        vbNullChar) - 1))
                    If UCase(szValueName) = "PATH" Then
                        ' we found the path the corresponds to the shared 
                        ' resource
                        Path = Trim(Left$(szValue, InStr(szValue, _
                            vbNullChar) - 1))
                        If UCase(Path) = UCase(Left(pathName, Len(Path))) Then
                            GetUNCName95 = "\\" & computerName & "\" & _
                                szResourceName & Mid$(pathName, Len(Path))
                            exitFlag = True
                        End If
                        exitw = True
                    End If
                End If
                j = j + 1
            Loop
            exitw = False
            RegCloseKey hKey2
        End If
        i = i + 1
    Loop
    
    RegCloseKey hKey
    
    If GetUNCName95 = "" Then GetUNCName95 = pathName
    
End Function

' Private function that does the work under Windows NT

Private Function GetUNCNameNT(pathName As String) As String
    Dim hKey As Long
    Dim hKey2 As Long
    Dim exitFlag As Boolean
    Dim i As Double
    Dim ErrCode As Long
    Dim rootKey As String
    Dim key As String
    Dim computerName As String
    Dim lComputerName As Long
    Dim stPath As String
    Dim firstLoop As Boolean
    Dim ret As Boolean

    ' first, verify whether the disk is connected to the network
    If Mid(pathName, 2, 1) = ":" Then
        Dim UNCName As String
        Dim lenUNC As Long
        
        UNCName = String$(520, 0)
        lenUNC = 520
        ErrCode = WNetGetConnection(Left(pathName, 2), UNCName, lenUNC)

        If ErrCode = 0 Then
            UNCName = Trim(Left$(UNCName, InStr(UNCName, vbNullChar) - 1))
            GetUNCNameNT = UNCName & Mid(pathName, 3)
            Exit Function
        End If
    End If
    
    ' else, scan the registry looking for shared resources (NT version)
    computerName = String$(255, 0)
    lComputerName = Len(computerName)
    ErrCode = GetComputerName(computerName, lComputerName)
    If ErrCode <> 1 Then
        GetUNCNameNT = pathName
        Exit Function
    End If
    
    computerName = Trim(Left$(computerName, InStr(computerName, _
        vbNullChar) - 1))
    rootKey = "SYSTEM\CurrentControlSet\Services\LanmanServer\Shares"
    ErrCode = RegOpenKey(HKEY_LOCAL_MACHINE, rootKey, hKey)
    
    If ErrCode <> 0 Then
        GetUNCNameNT = pathName
        Exit Function
    End If
    
    firstLoop = True
    
    Do Until exitFlag
        Dim szValue As String
        Dim szValueName As String
        Dim cchValueName As Long
        Dim dwValueType As Long
        Dim dwValueSize As Long
                
        szValueName = String(1024, 0)
        cchValueName = Len(szValueName)
        szValue = String$(500, 0)
        dwValueSize = Len(szValue)
        
        ' loop on "i" to access all shared DLLs
        ' szValueName will receive the key that identifies an element
        ErrCode = RegEnumValue(hKey, i#, szValueName, cchValueName, 0, _
            dwValueType, szValue, dwValueSize)
        
        If ErrCode <> 0 Then
            If Not firstLoop Then
                exitFlag = True
            Else
                i = -1
                firstLoop = False
            End If
        Else
            stPath = GetPath(szValue)
            If firstLoop Then
                ret = (UCase(stPath) = UCase(pathName))
                stPath = ""
            Else
                ret = (UCase(stPath) = UCase(Left$(pathName, Len(stPath))))
                stPath = Mid$(pathName, Len(stPath))
            End If
            If ret Then
                exitFlag = True
                szValueName = Left$(szValueName, cchValueName)
                GetUNCNameNT = "\\" & computerName & "\" & szValueName & stPath
            End If
        End If
        i = i + 1
    Loop
    
    RegCloseKey hKey
    If GetUNCNameNT = "" Then GetUNCNameNT = pathName
End Function

' support routine

Private Function GetPath(st As String) As String
    Dim pos1 As Long, pos2 As Long, pos3 As Long
    Dim stPath As String

    pos1 = InStr(st, "Path")
    If pos1 > 0 Then
        pos2 = InStr(pos1, st, vbNullChar)
        stPath = Mid$(st, pos1, pos2 - pos1)
        pos3 = InStr(stPath, "=")
        If pos3 > 0 Then
            stPath = Mid$(stPath, pos3 + 1)
            GetPath = stPath
        End If
    End If
End Function


Marco Losavio
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap