Amazon.com Widgets

Unix style mount points...

One of the devs on the BCL team created this cool little sample while investigation a Whidbey bug and I thought I’d share it with you…

 

C:\code >mount a: c:\MountPoint

Managed Unix-style mount program

Mounting volume a:\ at c:\MountPoint\

 

C:\code >dir c:\MountPoint

 Volume in drive C is Brian

 Volume Serial Number is 186C-51E7

 

 Directory of c:\MountPoint

 

01/27/2003  03:11 AM            15,229 Queue.cs

01/27/2003  06:10 PM            44,098 SortedDictionary.cs

01/27/2003  03:26 AM            11,100 Stack.cs

               3 File(s)         70,427 bytes

           

Here is the code…  Works fine for me on my Everett windows XP machine…  

 

using System;

using System.Runtime.InteropServices;

using System.Text;

using System.IO;

using System.ComponentModel;

 

public class UnixLikeMountProgram

{

    [DllImport("kernel32", CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)]

    private static extern bool GetVolumeNameForVolumeMountPoint(String volumeName, StringBuilder uniqueVolumeName, int uniqueNameBufferCapacity);

 

    // unique volume name must be "\\?\Volume{GUID}\"

    [DllImport("kernel32", CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)]

    private static extern bool SetVolumeMountPoint(String mountPoint, String uniqueVolumeName);

 

    [DllImport("kernel32", CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)]

    private static extern bool DeleteVolumeMountPoint(String mountPoint);

 

 

    private static void Usage()

    {

        Console.WriteLine();

        Console.WriteLine("mount <volume name> <mount point>");

        Console.WriteLine("mount -u <mount point>");

    }

 

    private static void Mount(string volumeName, string mountPoint)

    {

        Console.WriteLine("Mounting volume {0} at {1}", volumeName, mountPoint);

        bool r;

        StringBuilder sb = new StringBuilder(1024);

        r = GetVolumeNameForVolumeMountPoint(volumeName, sb, sb.Capacity);

        if (!r)

            throw new Win32Exception(Marshal.GetLastWin32Error());

 

        String uniqueName = sb.ToString();

        r = SetVolumeMountPoint(mountPoint, uniqueName);

        if (!r)

            throw new Win32Exception(Marshal.GetLastWin32Error());

    }

 

    private static void Unmount(string mountPoint)

    {

        Console.WriteLine("Unmounting the volume at {0}", mountPoint);

 

        bool r = DeleteVolumeMountPoint(mountPoint);

        if (!r)

            throw new Win32Exception(Marshal.GetLastWin32Error());

    }

 

    private static void Main(string[] args)

    {

        Console.WriteLine("Managed Unix-style mount program");

 

        if (args.Length != 2) {

            Usage();

            return;

        }

 

        bool unmount = false;

        String volumeName = null;

        String mountPoint = args[1];

       

        if (args[0].Equals("-u") || args[0].Equals("/u"))

            unmount = true;

        else {

            volumeName = args[0];

 

            if (volumeName[volumeName.Length - 1] != Path.DirectorySeparatorChar)

                volumeName += Path.DirectorySeparatorChar;

        }

 

        if (mountPoint[mountPoint.Length - 1] != Path.DirectorySeparatorChar)

            mountPoint += Path.DirectorySeparatorChar;

 

        if (unmount)

            Unmount(mountPoint);

        else

            Mount(volumeName, mountPoint);

    }

 

}

Published 01 April 04 03:35 by BradA
Filed under:

Comments

# Jerry Pisk said on April 1, 2004 3:47 PM:
Nice, Disk Management won't let you mount floppy drives...
# Brian Grunkemeyer said on April 1, 2004 4:25 PM:
One word of warning - Directory.Delete currently will recurse through mount points. So if you mount all of D:\ into C:\test\Mount, then call Directory.Delete("C:/test/Mount", true), we will delete everything on D:\. The same thing will happen if you delete C:\test recursively. The same will happen with symbolic links in Longhorn. I'd also be very careful with any pre-Longhorn tools like CMD's "del /s".

I'm fixing Directory.Delete in Whidbey to only delete the mount point (or symbolic link) itself. We may give the incorrect behavior for users in some small percentage of the time, but it's vastly less destructive than accidentally deleting an entire disk. Perhaps in a future version we'll add a flag to control this behavior.
# Roy J. Salisbury @ VsDevCentral said on April 1, 2004 5:40 PM:
I knew of the API's to do this, but had no idea it was so easy. One thing that I can't figure out however is how the Win2K resource kit utility "LINKD" works. It allows you to graft one folder onto another. Any ideas? I'm sure the process is just as simple, as this one, but can't find the API's that it uses.


# JackRazz said on April 1, 2004 5:40 PM:
Cool code. I successfully unmounted my volume "f:\". But when I try to remount the volume via a 'mount("f:\"," f:\") call, I get an error in the mount routine.

It appears that GetVolumeNameForVolumeMountPoint fails when the volume isn't mounted. I remounted manually via diskpart and then called unmount and copied the uniqueName into a constant. After setting it in the code with a constant, it works

Anyone have any ideas as to why GetVolumeNameForVolumeMountPoint won't work on an unmounted volume. Is ther a way around this?

JackRazz
# TrackBack said on April 2, 2004 2:56 AM:
LSN WebLog &raquo; Unix style mount points&#8230; for windows
# Jerry Pisk said on April 2, 2004 12:08 AM:
Brian, you may also "fix" it so it doesn't really delete anything, you'd make it even less destructive. What kind of an argument is it? If I tell the system to delete everything in a directory then I mean delete everything in that directory.
# Andrew Pechersky said on April 2, 2004 5:29 AM:
There is an open source utility by Mark Russinovich called Junction which does the same as LINKD from Windows 2000 RK. The feature of symbolic links was introduced since NTFS 5, so there is no problem to create utilities like this.
# Sam Gentile's Blog said on April 2, 2004 8:52 AM:
# Sam Gentile's Blog said on April 2, 2004 8:52 AM:
# Michael Moulton said on April 2, 2004 8:21 AM:
Thanks! I've been wishing for this for a while. We have a third-party product hardcoded to put files in a certain folder; this will allow us to mount a network volume on that folder so the output will go to a central location.
# Willy Denoyette MVP said on April 2, 2004 12:02 PM:
And following is a version using System.Management, this one needs W2K3 on the server, but with the advantage that it can mount volumes on remote servers.
(Sure, you need to love WMI).

Willy.

using System;
using System.Management;
using System.IO;
class App {
private static void Main(string[] args)
{
Console.WriteLine("Managed Unix-style mount program using System.Management");
if (args.Length != 2) {
Usage();
return;
}
String volumeName = null;
String mountPoint = args[1];
if (mountPoint[mountPoint.Length - 1] != Path.DirectorySeparatorChar)
mountPoint += Path.DirectorySeparatorChar;
MountVol M = new MountVol("celeb\\administrator", "Kevin111", "scenic"); // Remote connection (W2k3)
// MountVol M = new MountVol(); // local machine (W2K3 !!!)
if (args[0].Equals("-u") || args[0].Equals("/u"))
M.DisMount(mountPoint.Replace(":\\", ":\\\\\\\\"));
else {
volumeName = args[0];
M.Mount(volumeName, mountPoint);
}
}
private static void Usage()
{
Console.WriteLine();
Console.WriteLine("mount <volume name> <mount point>");
Console.WriteLine("mount -u <mount point>");
}
}
class MountVol
{
private ManagementBaseObject inputArgs = null;
private ManagementBaseObject outParams = null;
private uint ret = 0;
private ConnectionOptions co;
private ManagementScope scope;

public MountVol(string ConnectionUser, string ConnectionPassword, string Machine )
{
co = new ConnectionOptions();
co.Username = ConnectionUser;
co.Password = ConnectionPassword;
scope = new ManagementScope(@"\\" + Machine + @"\root\cimv2", co);
}
public MountVol() : this("", "", ".")
{}
public void Mount(string volumeName, string mountPoint)
{
// Register mountpoint and mount volume (corresponding to driveletter)
string strSQL = "select DeviceId FROM Win32_Volume WHERE driveletter='" + volumeName + "'" ;
SelectQuery query = new SelectQuery(strSQL);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
foreach(ManagementObject mountVol in searcher.Get())
{
inputArgs = mountVol.GetMethodParameters("AddMountPoint");
inputArgs["Directory"] = mountPoint;
outParams = mountVol.InvokeMethod("AddMountPoint", inputArgs, null);
ret = Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);
if(ret == 0) {
outParams = mountVol.InvokeMethod("Mount", null, null);
ret = Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);
}
mountVol.Dispose();
Console.WriteLine("Volume: {0} mounted", mountVol["DeviceId"].ToString());
}
}
}
public void DisMount(string mountPoint)
{
String strSQL = "select * FROM Win32_MountPoint WHERE Directory=\"Win32_Directory.Name=\\\"" + mountPoint + "\"\"" ;
SelectQuery query = new SelectQuery(strSQL);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher (scope, query))
{
foreach(ManagementObject mountVol in searcher.Get())
{
mountVol.Delete(); // delete mountpoint
mountVol.Dispose();
}
}
}
}
# Josh said on April 2, 2004 2:56 PM:
That's very cool. However, can you figure out a way to make a symbolic link if you don't have NTFS? :)
# TheNetAvenger said on April 2, 2004 5:04 PM:
To: Josh

>>That's very cool. However, can you figure out a way to make a symbolic
>>link if you don't have NTFS? :)

FAT/FAT32 are old technologies that do not have the same capabilities of NTFS, one of them being symbolic links.

NTFS has many advantages over FAT/FAT32, and if you are using your computer for performance, stability, or security; NTFS is the only real option for this in the Windows world.

NTFS is has a very good design and architecture and has been doing things for years that even other FS on other platforms are just now starting to offer. Even many *nixes have been trying to replicate many of the features in NTFS for years now. (Journaling, Security Encryption, on the fly Compression, etc)

A good example of this is Apple's implementation of journalling in OSX's file system, it is turned off by default for perfmance reasons, even though NTFS was doing journaling back in 1992 on 486 computers with little to no performance loss back then.
# Roshan James [MVP] said on April 6, 2004 10:40 PM:
Very Nice Anand,

I thought I'd just dump some of the API that might be relevant

C:\WINNT\system32>trashbin KERNEL32.DLL /exp |findstr /i mount
[ 101] 0x034276 <-- #102 : DeleteVolumeMountPointA()
[ 102] 0x034432 <-- #103 : DeleteVolumeMountPointW()
[ 172] 0x032c44 <-- #173 : FindFirstVolumeMountPointA()
[ 173] 0x033058 <-- #174 : FindFirstVolumeMountPointW()
[ 179] 0x03315e <-- #180 : FindNextVolumeMountPointA()
[ 180] 0x0333ae <-- #181 : FindNextVolumeMountPointW()
[ 187] 0x0333c4 <-- #188 : FindVolumeMountPointClose()
[ 407] 0x0333d0 <-- #408 : GetVolumeNameForVolumeMountPointA()
[ 408] 0x0339c2 <-- #409 : GetVolumeNameForVolumeMountPointW()
[ 706] 0x033c21 <-- #707 : SetVolumeMountPointA()
[ 707] 0x033f49 <-- #708 : SetVolumeMountPointW()

Neat huh ? But like someone else said, I didnt know it was so easy.

How does linkd work? Basically NTFS has support for these sort of things, which my understainf is, is that it is not supported by the win32 subsystem - basically you will have to look into ntdll.dll api exports.

That said, DO take a look at SFU, it brings out so much of the latent power inNT, it is simply stunning.
# Eric said on April 7, 2004 3:42 PM:
Interesting Brian, by 'fixing' Delete you are making an intractible probem?

How do I then delete the (now un-)mounted drive? Or discover that it was there?

I'm not actually objecting to the new behavior, I just wonder when 'a little change here' doesn't appear to be completly thought through. You'll get the opposite number reporting now that the command didn't do what they thought it would (actually remove files).
# Geek Noise said on May 1, 2004 12:40 PM:
# Brad Abrams Unix style mount points | Hair Growth Products said on June 9, 2009 4:21 AM:

PingBack from http://hairgrowthproducts.info/story.php?id=7138

New Comments to this post are disabled

Search

Go

This Blog

Syndication

Page view tracker