Type a page name and press Enter. You'll jump to the page if it exists, or you can create it if it doesn't.
To create a page in a module other than advapi32, prefix the name with the module name and a period.
WNetGetUniversalName (advapi32)
.
C# Signature:
[DllImport("mpr.dll", CharSet=CharSet.Auto)]
[return:MarshalAs(UnmanagedType.U4)]
static extern int WNetGetUniversalName(
string lpLocalPath,
[MarshalAs(UnmanagedType.U4)] int dwInfoLevel,
IntPtr lpBuffer,
[MarshalAs(UnmanagedType.U4)] ref int lpBufferSize);
VB.NET Signature:
<DllImport("mpr.dll", CharSet=CharSet.Auto)> _
Private Shared Function WNetGetUniversalName(lpLocalPath As String, <MarshalAs(UnmanagedType.U4)> dwInfoLevel As Integer, lpBuffer As IntPtr, <MarshalAs(UnmanagedType.U4)> ByRef lpBufferSize As Integer) As <MarshalAs(UnmanagedType.U4)> Integer
End Function
Constants:
const int UNIVERSAL_NAME_INFO_LEVEL = 0x00000001;
const int REMOTE_NAME_INFO_LEVEL = 0x00000002;
const int ERROR_MORE_DATA = 234;
const int NOERROR = 0;
// The pointer in memory to the structure.
IntPtr buffer = IntPtr.Zero;
// Wrap in a try/catch block for cleanup.
try
{
// First, call WNetGetUniversalName to get the size.
int size = 0;
// Make the call.
// Pass IntPtr.Size because the API doesn't like null, even though
// size is zero. We know that IntPtr.Size will be
// aligned correctly.
int apiRetVal = WNetGetUniversalName(localPath, UNIVERSAL_NAME_INFO_LEVEL, (IntPtr) IntPtr.Size, ref size);
// If the return value is not ERROR_MORE_DATA, then
// raise an exception.
if (apiRetVal != ERROR_MORE_DATA)
// Throw an exception.
throw new Win32Exception(apiRetVal);
// Allocate the memory.
buffer = Marshal.AllocCoTaskMem(size);
// Now make the call.
apiRetVal = WNetGetUniversalName(localPath, UNIVERSAL_NAME_INFO_LEVEL, buffer, ref size);
// If it didn't succeed, then throw.
if (apiRetVal != NOERROR)
// Throw an exception.
throw new Win32Exception(apiRetVal);
// Now get the string. It's all in the same buffer, but
// the pointer is first, so offset the pointer by IntPtr.Size
// and pass to PtrToStringAuto.
retVal = Marshal.PtrToStringAuto(new IntPtr(buffer.ToInt64() + IntPtr.Size));
}
finally
{
// Release the buffer.
Marshal.FreeCoTaskMem(buffer);
}
// First, allocate the memory for the structure.
// That's all folks.
return retVal;
}
Notes:
Note by Jason Bird 2010-10-13
Regarding Günter's note below - you must make sure to specify 'CharSet=CharSet.Auto' in the DllImport declaration in order for PtrToStringAuto to work correctly. This tells the method to marshal the string according to the default for the underlying OS - the same default used by PtrToStringAuto to determine how to decode the string.
Note by Günter Prossliner 2005-08-29
PtrToStringAuto doesn't work on my system. I have tested in on a clean WindowsXP professional maschine. The PtrToStringAuto function just returns garbage. After stepping into the function with the debugger I was looking a the Memory - Windows pointing to the address of "buffer". What I've seen there was a "normal" zero - terminated ANSI String.
int actualLength = retVal.IndexOf('\0'); // Returned string has a bunch of 0's at the end.
// Remove everything from the first '\0' onwards.
if (actualLength >= 0) {
retVal = retVal.Substring(0, actualLength);
}
If you take a look at the IL - Code of Marshal.PtrToStringAuto(IntPtr) you can see that this function calls 'kernel32:lstrlen' and 'kernel32:lstrcpy' using a buffer (StringBuilder) with the size of lstrlen.
The code of Marshal.PtrToStringAuto(IntPtr, Int32 size) looks quite different: It checks out the Marshal.SystemDefaultCharSize field and simply calls 'PtrToStringAnsi' or 'PtrToStringUni'.
Tips & Tricks:
Please add some!
Sample Code:
/* This needs cleaning up -- errr but I'm paid by the hour so I don't have the time. I mostly ripped the wrapper and modified it. It provides an alternative to pointer arithmetic though...*/
/*
typedef struct _REMOTE_NAME_INFO
{
LPTSTR lpUniversalName;
LPTSTR lpConnectionName;
LPTSTR lpRemainingPath;
} REMOTE_NAME_INFO;
*/
[StructLayout(LayoutKind.Sequential)]
struct _REMOTE_NAME_INFO
{
public IntPtr lpUniversalName;
public IntPtr lpConnectionName;
public IntPtr lpRemainingPath;
}
public struct RemoteNameInfo
{
public string universalName;
public string connectionName;
public string remainingPath;
}
public class WNet
{
const int UNIVERSAL_NAME_INFO_LEVEL = 0x00000001;
const int REMOTE_NAME_INFO_LEVEL = 0x00000002;
const int ERROR_MORE_DATA = 234;
const int ERROR_NOT_CONNECTED = 2250;
const int NOERROR = 0;
[DllImport("mpr.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.U4)]
private static extern int WNetGetUniversalNameW(
string lpLocalPath,
[MarshalAs(UnmanagedType.U4)] int dwInfoLevel,
IntPtr lpBuffer,
[MarshalAs(UnmanagedType.U4)] ref int lpBufferSize);
public static RemoteNameInfo GetRemoteNameInfo(string localPath)
{
// The return value.
RemoteNameInfo retVal;
_REMOTE_NAME_INFO rni;
// The pointer in memory to the structure.
IntPtr buffer = IntPtr.Zero;
// Wrap in a try/catch block for cleanup.
try
{
// First, call WNetGetUniversalName to get the size.
int size = 0;
// Make the call.
// Pass IntPtr.Size because the API doesn't like null, even though
// size is zero. We know that IntPtr.Size will be
// aligned correctly.
int apiRetVal = WNetGetUniversalNameW(localPath, REMOTE_NAME_INFO_LEVEL, (IntPtr)IntPtr.Size, ref size);
// if the return value is ERROR_NOT_CONNECTED, then
// this is a local path
if (apiRetVal == ERROR_NOT_CONNECTED)
{
retVal = new RemoteNameInfo();
retVal.connectionName = Path.GetPathRoot(localPath);
retVal.remainingPath = localPath.Substring(Path.GetPathRoot(localPath).Length);
retVal.universalName = localPath;
return retVal;
}
// If the return value is not ERROR_MORE_DATA, then
// raise an exception.
if (apiRetVal != ERROR_MORE_DATA)
// Throw an exception.
throw new System.ComponentModel.Win32Exception();
// Allocate the memory.
buffer = Marshal.AllocCoTaskMem(size);
// Now make the call.
apiRetVal = WNetGetUniversalNameW(localPath, REMOTE_NAME_INFO_LEVEL, buffer, ref size);
// If it didn't succeed, then throw.
if (apiRetVal != NOERROR)
// Throw an exception.
throw new System.ComponentModel.Win32Exception();
// Now get the string. It's all in the same buffer, but
// the pointer is first, so offset the pointer by IntPtr.Size
// and pass to PtrToStringAuto.
//retVal = Marshal.PtrToStringAuto(new IntPtr(buffer.ToInt64() + IntPtr.Size));
// First, allocate the memory for the structure.
// That's all folks.
}
}
.NET Use in VB
by Mike Gerbi
12/05/2007
Make A New Class
Imports System.Runtime.InteropServices
Namespace Custom.Win32
'You can add more functionality from this DLL in this namespace and import it in future projects to get everything.
Public Class MPR_DotNET_Version
Private bufSize As Integer = 1000
Private myPath As String = ""
Private lpBuffer As IntPtr = Marshal.AllocHGlobal(bufSize)
Public Enum INFO_LEVEL As Integer
UNIVERSAL_NAME_INFO_LEVEL = 1
REMOTE_NAME_INFO_LEVEL = 2
End Enum
Public Sub New(ByVal path As String)
myPath = path
End Sub
Public Function GetUnivseralName() As String
Dim uname As New UNIVERSAL_NAME_INFO
Try
Dim result As String = myPath
Dim ret As Int32 = GetUName(result, INFO_LEVEL.UNIVERSAL_NAME_INFO_LEVEL, lpBuffer, bufSize)
If ret = 0 Then
Marshal.PtrToStructure(lpBuffer, uname)
ElseIf ret = 2250 Then
Throw New ArgumentException("Not Connected")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
Marshal.FreeHGlobal(lpBuffer)
End Try
Return uname.UniversalName.ToString
End Function
<DllImport("mpr.dll", Entrypoint:="WNetGetUniversalName", CharSet:=CharSet.Auto, SetLastError:=False)> _
Private Shared Function GetUName(ByVal Path As String, ByVal outName As INFO_LEVEL, _
ByVal bObj As IntPtr, ByRef bSize As Integer) As Integer
End Function
End Class
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto), Serializable()> Class UNIVERSAL_NAME_INFO
<MarshalAs(UnmanagedType.LPTStr)> Public UniversalName As String
<MarshalAs(UnmanagedType.LPTStr)> Public ConnectionName As String
<MarshalAs(UnmanagedType.LPTStr)> Public RemainingPath As String
Dim result As DialogResult = mainFolderBrowserDialog.ShowDialog
If result = Windows.Forms.DialogResult.OK Then
Dim dirInfo As DirectoryInfo = New DirectoryInfo(mainFolderBrowserDialog.SelectedPath)
path = mainFolderBrowserDialog.SelectedPath
'Here I get the UNC path and use it later in another routine.
Dim UNI As MPR_DotNET_Version = New MPR_DotNET_Version(path)
path = UNI.GetUnivseralName
For Each f As FileInfo In dirInfo.GetFiles
If f.Extension = ".txt" Then
TextFileListView.Items.Add(f.Name)
ElseIf f.Extension = ".pdf" Then
PDFListView.Items.Add(f.Name)
End If
Next
ElseIf result = Windows.Forms.DialogResult.Cancel Then
Me.Close()
Else
Throw New System.Exception
End If
Catch ex As System.Exception
MsgBox(ex.Message)
WriteToErrorLog(ex)
End Try
End Sub
Alternative VB.Net Translation
by Sean Kendrick (Jaeden "Sifo Dyas" al'Raec Ruiner)
After some overview, and minor deliberation, I've flushed out a full port of the above manifestations, finding not only the best of both the other contributions, but also a little of my own designs for personal use. I needed this design for SQL Server, as utilizing Ad-Hoc queries across network lines the Server inherently treats "C:\" as the local drive on the Server, so for a query on a client system that needs to be translated to "\\MyComputer\C$" in order to be functional. I apologize as well for my little extension, but with my enjoyment of C style assignment and comparison in one step, I created that for my own use, and did not wish to alter my class in order to post it here, so I included it. I also noticed that the Marshal.PtrToStringAnsi() did not work for me, while PtrToStringAuto did, so I am currently unaware how I might test for which is the best to use for any given situation, but I figure anyone can make that minor alteration if necessary on their own.
<System.Runtime.CompilerServices.Extension()> _
Public Function Assign(Of T)(ByRef self As T, ByVal Val As T) As T
self = Val
Return Val
End Function
''' <summary>
''' Not Inhertitable Shared Class that Computes and Returns the UNC Path for any file or directory,
''' Providing not only the Original Path String, but also the UNC formatted string using Default Shares
''' for Local Files.
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class UNCPath
Implements IDisposable
#Region "-------------::< Fields & Constants >::-------------"
Private Const UNIVERSAL_NAME_INFO_LEVEL As Integer = 1
Private Const REMOTE_NAME_INFO_LEVEL As Integer = 2
Private Const NO_ERROR As Integer = 0
Private Const ERROR_MORE_DATA As Integer = 234
Private Const ERROR_NOT_CONNECTED As Integer = 2250
Private Const UNCFMT As String = "\\{0}\{1}$\{2}"
Private _origpath As String = ""
Private _local As Boolean = False
Private _error As Integer = NO_ERROR
Private _fi As IO.FileInfo = Nothing
Private _di As IO.DirectoryInfo = Nothing
Private _isfile As Boolean = False
Private disposedValue As Boolean = False ' To detect redundant calls
Private _unc As String
Private _connect As String
Private _path As String
#End Region
#Region "-------------::< Class Properties >::-------------"
''' <summary>
''' Gets UNC Fully Qualified Path to File or Directory
''' </summary>
''' <returns>String</returns>
''' <remarks></remarks>
Public ReadOnly Property UNCName() As String
Get
Return _unc
End Get
End Property
''' <summary>
''' Gets the Connection or UNC Initial Share Point [\\ComputerName\Share]
''' </summary>
''' <returns>String</returns>
''' <remarks></remarks>
Public ReadOnly Property Connection() As String
Get
Return _connect
End Get
End Property
''' <summary>
''' Gets the Path location within the Connection to the Directory or File
''' </summary>
''' <returns>String</returns>
''' <remarks></remarks>
Public ReadOnly Property Path() As String
Get
Return _path
End Get
End Property
''' <summary>
''' Gets the Original File/Directory provided the UNCPath Class
''' </summary>
''' <returns>String</returns>
''' <remarks></remarks>
Public ReadOnly Property OriginalPath() As String
Get
Return _origpath
End Get
End Property
''' <summary>
''' Gets a flag indicating if the Original File is on a Local Drive
''' </summary>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Public ReadOnly Property IsLocal() As Boolean
Get
Return _local
End Get
End Property
''' <summary>
''' Gets the Last Error information incase it all goes pear shaped.
''' </summary>
''' <returns>Integer</returns>
''' <remarks></remarks>
Public ReadOnly Property LastError() As Integer
Get
Return _error
End Get
End Property
''' <summary>
''' Gets a flag indicating if the Target is a File
''' </summary>
''' <returns>Boolean</returns>
''' <remarks></remarks>
Public ReadOnly Property IsFile() As Boolean
Get
Return _isfile
End Get
End Property
''' <summary>
''' Gets an IO.FileInfo Object Pointing to the UNC Shared File
''' </summary>
''' <returns>IO.FileInfo</returns>
''' <remarks>Returns Nothing if the Provided Path was a Directory</remarks>
Public ReadOnly Property File() As IO.FileInfo
Get
Return _fi
End Get
End Property
''' <summary>
''' Gets an IO.DirectoryInfo Object pointing to the UNC Share
''' </summary>
''' <returns>IO.DirectoryInfo</returns>
''' <remarks>Returns the Directory of the File if the Provided Path was a File</remarks>
Public ReadOnly Property Directory() As IO.DirectoryInfo
Get
Return _di
End Get
End Property
#End Region
#Region "-------------::< Class Constructors >::-------------"
''' <summary>
''' Private Constructor
''' </summary>
''' <param name="Path">Fully Qualified Path to File or Directory</param>
''' <remarks></remarks>
Private Sub New(ByVal Path As String)
_origpath = Path
GetUnivseralName()
If _error = NO_ERROR Then
If _isfile.Assign(IO.File.Exists(Path)) Then
_fi = New IO.FileInfo(_unc)
_di = _fi.Directory
Else : _di = New IO.DirectoryInfo(_unc)
End If
End If
End Sub
#End Region
#Region "-------------::< Shared Methods >::-------------"
''' <summary>
''' Returns a IO.FileInfo object to the UNC Qualified Path to a File.
''' </summary>
''' <param name="filepath">Fully Qualifie Path, either with UNC, Local, or Mapped Drive to a file</param>
''' <returns>If the Path is not a file or an error, returns Nothing, else IO.FileInfo</returns>
''' <remarks></remarks>
Public Shared Function GetUNCFile(ByVal filepath As String) As IO.FileInfo
Dim unc As UNCPath = GetUNCPath(filepath)
Dim fi As IO.FileInfo = unc.File
unc.Free()
Return fi
End Function
''' <summary>
''' Returns a IO.DirectoryInfo object to the UNC Qualified Path to a Directory, or the Directory containing a File
''' </summary>
''' <param name="filepath">Fully Qualifie Path, either with UNC, Local, or Mapped Drive to either a File or a Directory</param>
''' <returns>On Error, Returns Nothing, else IO.DirectoryInfo</returns>
''' <remarks></remarks>
Public Shared Function GetUNCDir(ByVal filepath As String) As IO.DirectoryInfo
Dim unc As UNCPath = GetUNCPath(filepath)
Dim di As IO.DirectoryInfo = unc.Directory
unc.Free()
Return di
End Function
''' <summary>
''' Creates a UNCPath object to a File or Directory and returns whether or the operation was successful.
''' </summary>
''' <param name="FilePath">Fully Qualifie Path, either with UNC, Local, or Mapped Drive</param>
''' <param name="UNC">Reference Passed UNCPath Object to Return</param>
''' <returns>Boolean - Success/Failure</returns>
''' <remarks></remarks>
Public Shared Function GetUNCPath(ByVal FilePath As String, ByRef UNC As UNCPath) As Boolean
UNC = GetUNCPath(FilePath)
Return (UNC IsNot Nothing) AndAlso (UNC.LastError = NO_ERROR)
End Function
''' <summary>
''' Returns a UNCPath object to a File or Directory
''' </summary>
''' <param name="FilePath">Fully Qualifie Path, either with UNC, Local, or Mapped Drive to either a File or a Directory</param>
''' <returns>UNCPath</returns>
''' <remarks></remarks>
Public Shared Function GetUNCPath(ByVal FilePath As String) As UNCPath
Return New UNCPath(FilePath)
End Function
#End Region
#Region "-------------::< Public Methods >::-------------"
#Region " IDisposable Support "
''' <summary>
''' This code added by Visual Basic to correctly implement the disposable pattern.
''' </summary>
''' <remarks></remarks>
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#End Region
#Region "-------------::< Private Methods >::-------------"
''' <summary>
''' Retrieves the Unversal Naming Convention for the provided Path, using the Win32 API MPR.DLL
''' </summary>
''' <remarks></remarks>
Private Sub GetUnivseralName()
Dim lpBuffer As IntPtr = IntPtr.Zero
Try
Dim size As Integer = 0
_error = WNetGetUniversalName(_origpath, REMOTE_NAME_INFO_LEVEL, CType(IntPtr.Size, IntPtr), size)
If _local.Assign(_error = ERROR_NOT_CONNECTED) Then
' local file so process locally, original file still maintains the C:\ notation
' but UNCName is formatted to appear using the default [Drive]$ share of the system.
_connect = IO.Path.GetPathRoot(_origpath)
_path = _origpath.Substring(_connect.Length)
_unc = String.Format(UNCFMT, My.Computer.Name, _connect(0), _path)
ElseIf _error = ERROR_MORE_DATA Then
'received buffer size from initial call so allocate memory an re-call for actual data
lpBuffer = Marshal.AllocCoTaskMem(size)
If _error.Assign(WNetGetUniversalName(_origpath, REMOTE_NAME_INFO_LEVEL, lpBuffer, size)) = NO_ERROR Then
Dim rni As _REMOTE_NAME_INFO 'if call successful convert data over from buffer structure to actual strings
rni = CType(Marshal.PtrToStructure(lpBuffer, GetType(_REMOTE_NAME_INFO)), _REMOTE_NAME_INFO)
_connect = Marshal.PtrToStringAuto(rni.lpConnectionName)
_path = Marshal.PtrToStringAuto(rni.lpRemainingPath)
_unc = Marshal.PtrToStringAuto(rni.lpUniversalName)
Else : Throw New System.ComponentModel.Win32Exception(_error)
End If
Else : Throw New System.ComponentModel.Win32Exception(_error)
End If
Finally
Marshal.FreeCoTaskMem(lpBuffer) 'finalize marshal allocated memory
End Try
End Sub
''' <summary>
''' Implementis the IDisposable Inteface for usage with the Using operator
''' </summary>
''' <param name="disposing">Flag to Dispose Managed Code</param>
''' <remarks></remarks>
Private Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
End If
_fi = Nothing
_di = Nothing
End If
Me.disposedValue = True
End Sub
#Region "===========[ API DLL HEADERS ]============"
''' <summary>
''' DLL Header for the WNetGetUniversalName
''' </summary>
''' <param name="lpLocalPath">String containing the Full Path to the Object</param>
''' <param name="dwInfoLevel">Integer Flag indicating the Type of Structure to Return</param>
''' <param name="lpBuffer">IntPtr to the Buffer to receive the data</param>
''' <param name="lpBufferSize">Reference Passed Integer for the Size of the Buffer</param>
''' <returns>Integer</returns>
''' <remarks></remarks>
<DllImport("mpr.dll", Entrypoint:="WNetGetUniversalName", CharSet:=CharSet.Unicode, SetLastError:=False)> _
Private Shared Function WNetGetUniversalName(ByVal lpLocalPath As String, _
<MarshalAs(UnmanagedType.U4)> ByVal dwInfoLevel As Integer, _
ByVal lpBuffer As IntPtr, _
<MarshalAs(UnmanagedType.U4)> ByRef lpBufferSize As Integer) As <MarshalAs(UnmanagedType.U4)> Integer
End Function
#End Region
#Region "====[ INTERNAL STRUCTURE DECLARATION ]===="
''' <summary>
''' Remote Name Info Structure for use with the WNetGetUniveralName API Call
''' </summary>
''' <remarks></remarks>
<StructLayout(LayoutKind.Sequential)> _
Private Structure _REMOTE_NAME_INFO
Public lpUniversalName As IntPtr
Public lpConnectionName As IntPtr
Public lpRemainingPath As IntPtr
End Structure
#End Region
#End Region
End Class
Alternative Managed API:
Do you know one? Please contribute it!
This utilizes the WNetGetUniversalName method in MPR.dll. Once implemented, all you have to do is create an instance of the MPR_DotNET_Version class and use the GetUniversalName method. You can also add on to this class for other functionality if you choose. Hope this helps.
6/13/2012 12:15:52 PM - -24.132.191.153
TODO - a short description
3/16/2007 8:02:38 AM - -89.49.254.174
An IntPtr is a pointer to a memory location (unmanaged) that adapts to the platform it is running on (64-bit, etc.) UNLIKE a standard int/Integer. You should always use this type for unmanaged calls that require it, even though an int will appear to work on your development machine.
1/13/2008 4:00:13 AM - Damon Carr-72.43.165.29
An IntPtr is a pointer to a memory location (unmanaged) that adapts to the platform it is running on (64-bit, etc.) UNLIKE a standard int/Integer. You should always use this type for unmanaged calls that require it, even though an int will appear to work on your development machine.
1/13/2008 4:00:13 AM - Damon Carr-72.43.165.29
Click to read this page
10/2/2011 2:35:57 AM - txzhgh-89.110.151.174
An IntPtr is a pointer to a memory location (unmanaged) that adapts to the platform it is running on (64-bit, etc.) UNLIKE a standard int/Integer. You should always use this type for unmanaged calls that require it, even though an int will appear to work on your development machine.
1/13/2008 4:00:13 AM - Damon Carr-72.43.165.29
This utilizes the WNetGetUniversalName method in MPR.dll. Once implemented, all you have to do is create an instance of the MPR_DotNET_Version class and use the GetUniversalName method. You can also add on to this class for other functionality if you choose. Hope this helps.
6/13/2012 12:15:52 PM - -24.132.191.153
Please edit this page!
Do you have...
helpful tips or sample code to share for using this API in managed code?
corrections to the existing content?
variations of the signature you want to share?
additional languages you want to include?
Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).