Converting a mapped drive to a UNC path
Hello!
I've been running into clients with network setups who have been trying to install onto mapped network drives. This can cause issues, mainly because mapped drives are associated with User logons and can be different depending upon who is logged into a machine. Moreover, services do not obtain mapped drive information, even when given rights to "Log on as:" a particular user.
UNC paths, however, do not exhibit this problem. Thus, I wrote a little function to take any windows full path and, if the path uses a mapped drive, convert it to a UNC path.
Enjoy!!
#
# GetUniversalName.nsh - by HotButteredSoul
#
# Function for getting the Universal name of a filepath.
#
!ifndef _GetUniversalName_nsh
!define _GetUniversalName_nsh
#
# get_universal_name - gets universal name of a filepath
#
# Example:
#
# Push "H:\path\file"
# Call get_universal_name
# Pop $0 ; = "\\servername\sharename\path\file"
#
# Uses mpr.lib WNetGetUniversalNameA
#
# DWORD WNetGetUniversalName(
# LPCTSTR lpLocalPath, // pointer to drive-based path for a network
# // resource
# DWORD dwInfoLevel, // specifies form of universal name to be
# // obtained
# LPVOID lpBuffer, // pointer to buffer that receives universal
# // name data structure
# LPDWORD lpBufferSize // pointer to variable that specifies size
# // of buffer
# );
#
# Parameters
# lpLocalPath
# Points to a null-terminated string that is a drive-based path for a network resource.
# For example, if drive H has been mapped to a network drive share, and the network
# resource of interest is a file named SAMPLE.DOC in the directory \WIN32\EXAMPLES on
# that share, the drive-based path is H:\WIN32\EXAMPLES\SAMPLE.DOC.
#
# dwInfoLevel
# Specifies the type of data structure that the function will store in the buffer pointed
# to by lpBuffer. This parameter can be one of the following values: Value Meaning
# UNIVERSAL_NAME_INFO_LEVEL The function will store a UNIVERSAL_NAME_INFO data
# structure in the buffer. (defined in WINNETWK.H as 1)
# REMOTE_NAME_INFO_LEVEL The function will store a REMOTE_NAME_INFO data structure in
# the buffer. (defined in WINNETWK.H as 2)
#
# The UNIVERSAL_NAME_INFO data structure points to a Universal Naming Convention (UNC)
# name string.
#
# lpBuffer
# Points to a buffer that receives the type of data structure specified by the
# dwInfoLevel parameter.
#
# lpBufferSize
# Points to a variable that specifies the size in bytes of the buffer pointed to by lpBuffer.
# If the function succeeds, it sets the variable pointed to by lpBufferSize to the size
# in bytes of the data structure stored in the buffer. If the function fails because the
# buffer is too small, indicated by the ERROR_MORE_DATA error code, it sets the variable
# pointed to by lpBufferSize to the required buffer size.
#
# Return Values
# If the function succeeds, the return value is NO_ERROR (0).
#
# If the function fails, the return value is an error code. To get extended error
# information, callGetLastError. GetLastError may return one of the following error codes:
#
# Value Meaning
# ERROR_BAD_DEVICE The string pointed to by lpLocalPath is invalid (1200).
# ERROR_CONNECTION_UNAVAIL There is no current connection to the remote device, but there
# is a remembered (persistent) connection to it (1201).
# ERROR_EXTENDED_ERROR A network-specific error occurred. Use the WNetGetLastError
# function to obtain a description of the error (1208).
# ERROR_MORE_DATA The buffer pointed to by lpBuffer is too small. The function sets the
# variable pointed to by lpBufferSize to the required buffer size. More entries are
# available with subsequent calls (234).
# ERROR_NOT_SUPPORTED The dwInfoLevel parameter was set to UNIVERSAL_NAME_INFO_LEVEL, but
# the network provider does not support UNC names. This function is not supported by
# any of the network providers (282).
# ERROR_NO_NET_OR_BAD_PATH None of the providers recognized this local name as having a
# connection. However, the network is not available for at least one provider to whom
# the connection may belong (1203).
# ERROR_NO_NETWORK There is no network present (1222).
# ERROR_NOT_CONNECTED The device specified by lpLocalPath is not redirected (2250).
#
Function get_universal_name
Exch $0 ; local path (IN)
Push $1 ; Universal Path (OUT)
Push $2 ; lpBuffer
Push $3 ; lpBufferSize
Push $4 ; GetUniversalName return value
;allocate buffer for following structure:
; typedef struct _UNIVERSAL_NAME_INFO { /* uni */
; LPTSTR lpUniversalName;
; } UNIVERSAL_NAME_INFO;
System::Call "*(&t${NSIS_MAX_STRLEN} '') i .r2"
; make call
System::Call 'mpr::WNetGetUniversalNameA(t r0, i 1,i $2, *i ${NSIS_MAX_STRLEN} r3)i .r4'
IntCmp 0 $4 success
StrCpy $1 $0 ; failed, so just use local path
GoTo clean_up
success:
System::Call "*$2(t .r1)" ; Extract universal string
clean_up:
System::Free $2
Pop $4
Pop $3
Pop $2
Exch
Pop $0
Exch $1
FunctionEnd
!endif ; _GetUniversalName_nsh