Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine the Drive Letter of a mounted TrueCrypt volume

After a TrueCrypt container has been mounted to a drive letter, is it possible to determine in a batch file which container the drive letter was mounted from, or which drive letter the container was mounted to?

In a batch file, I want to mount a specified TrueCrypt container to a specified drive letter. TrueCrypt errors if the container is already mounted or if the drive letter isn't available, so I want to run TrueCrypt only if the specified container hasn't already been mounted to the specified drive letter, that is, only if the action hasn't been completed already.

Any suggestions would be appreciated.

Edit

Bounty Summary In short imagine you have volumes C:\Vol1.tc and C:\Vol2.tc mounted to drives X and Y. How can you tel that C:\Vol1.tc is mounted to drive X and C:\Vol2.tc to drive Y programaticaly with a batch file or C# code?

like image 270
Matthew White Avatar asked May 25 '13 19:05

Matthew White


People also ask

What drive letter can be used when mounting a TrueCrypt volume?

Mount this TrueCrypt Volume as drive letter F: E: and F: will both be shown in Windows, F: will contain the data, E: will not be accessible.

How do I unmount TrueCrypt volume?

4 Answers. You can use a terminal to unmount it. Also you can create a launcher to unmount it: 1) Paste this at terminal: gedit ~/Desktop/unmounttruecrypt.


2 Answers

A way to do that would be to directly ask to Truecrypt driver himself. This could be achieved with the DeviceIoControl function. In fact, that's exactly what the TrueCrypt GUI is doing.

Note that it's easier to do that in c++. You'll find a good article here.

The idea is to call the DeviceIoControl function, asking for the TC_IOCTL_GET_MOUNTED_VOLUMES You will obtain a structure, with all of the mounted volumes path and drive letters. In fact it's a 26 elements array (one for each possible drive letter), called wszVolume, which contain the path of the truecrypt volume which is mounted on.

Hope the following sample will help you find how to do in your case.

Sample Code in C# :

class Program
{
    static void Main(string[] args)
    {
        uint size = (uint)Marshal.SizeOf(typeof(MOUNT_LIST_STRUCT));
        IntPtr buffer = Marshal.AllocHGlobal((int)size);
        uint bytesReturned;
        IntPtr _hdev = CreateFile("\\\\.\\TrueCrypt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
        bool bResult = DeviceIoControl(_hdev, TC_IOCTL_GET_MOUNTED_VOLUMES, buffer, size, buffer, size, out bytesReturned, IntPtr.Zero);
        MOUNT_LIST_STRUCT mount = new MOUNT_LIST_STRUCT();
        Marshal.PtrToStructure(buffer, mount);
        Marshal.FreeHGlobal(buffer);

        for (int i = 0; i < 26; i++)
            Console.WriteLine("{0}: => {1}", (char)('A' + i), mount.wszVolume[i]);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    class MOUNT_LIST_STRUCT
    {
        public readonly UInt32 ulMountedDrives; /* Bitfield of all mounted drive letters */
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        public readonly MOUNT_LIST_STRUCT_VOLUME_NAME[] wszVolume;  /* Volume names of mounted volumes */
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        public readonly UInt64[] diskLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        public readonly int[] ea;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        public readonly int[] volumeType;   /* Volume type (e.g. PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    struct MOUNT_LIST_STRUCT_VOLUME_NAME
    {
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 260)]
        public readonly char[] wszVolume;   /* Volume names of mounted volumes */

        public override string ToString()
        {
            return (new String(wszVolume)).TrimEnd('\0');
        }
    }

    public static int CTL_CODE(int DeviceType, int Function, int Method, int Access)
    {
        return (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2)
          | (Method));
    }
    private static readonly uint TC_IOCTL_GET_MOUNTED_VOLUMES = (uint)CTL_CODE(0x00000022, 0x800 + (6), 0, 0);

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
    IntPtr lpInBuffer, uint nInBufferSize,
    IntPtr lpOutBuffer, uint nOutBufferSize,
    out uint lpBytesReturned, IntPtr lpOverlapped);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr CreateFile(
         [MarshalAs(UnmanagedType.LPTStr)] string filename,
         [MarshalAs(UnmanagedType.U4)] FileAccess access,
         [MarshalAs(UnmanagedType.U4)] FileShare share,
         IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
         [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
         [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
         IntPtr templateFile);
}
like image 147
Gerard Walace Avatar answered Sep 30 '22 15:09

Gerard Walace


This is what I have so far:

I am creating a custom app written in c# that informs the user what volumes are mounted/dismounted and if they are mounted I need to inform the user on what drive. In order to know if a volume is mounted I have the following class:

Note I make use of handle.exe that program can be downloaded at http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx or also from http://download.sysinternals.com/files/Handle.zip

Also I belive you must be running the program as an administrator

class TrueCryptHelp
{
    // I have that program on the working directory
    // it can be downloaded from http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx
    const string HandleExeLocation = "handle.exe"; 
    static string systemProcessFiles;
    static DateTime dateFilesLockedInfo = new DateTime();
    static string SystemProcessFiles
    {
        get
        {
            if ((DateTime.Now - dateFilesLockedInfo).TotalSeconds > 2)
            {
                Process p = new Process();
                var psi = new ProcessStartInfo();
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute = false;
                psi.FileName = HandleExeLocation;
                p.StartInfo = psi;
                p.Start();

                var output = p.StandardOutput.ReadToEnd();

                systemProcessFiles = string.Empty;

                foreach (Match m in Regex.Matches(output ?? "", @"(?sx) -{20}  [^-]  .+?  -{20}"))
                {
                    if (Regex.Match(m.Value ?? "", @"(?xi) -{10}  [\s\r\n]+  System \s pid").Success)
                    {
                        if (Regex.Match(m.Value ?? "", @"(?xi)  \) \s+ \\clfs \s* (\r|\n)").Success)
                        {
                            systemProcessFiles = m.Value.ToLower();
                            break;
                        }
                    }
                }

            }

            dateFilesLockedInfo = DateTime.Now;

            return systemProcessFiles;
        }
    }

    public static bool IsVolumeMounted(string volumeLocation)
    {
        //DriveInfo d = new System.IO.DriveInfo(volume.DriveLetter);
        //if (d == null)
        //return false;

        //if (d.DriveType != System.IO.DriveType.Fixed)
        //return false;

        //if ((d.DriveFormat ?? "").ToLower().Contains("fat") == false)
        //return false;

        if (SystemProcessFiles.Contains(volumeLocation.ToLower()))
        {
            return true;
        }
        else
        {
            return false;
        }

    }
}

then if I want to know if the volume located at C:\Users\Tono\Desktop\v1.tc is mounted I will call the method as:

var isVolMounted = TrueCryptHelp.IsVolumeMounted(@"A:\Users\Tono\Desktop\v1.tc");

Now I am missing to answer the question! With the class I posted I am able to know that the volume located at C:\Users\etc... is mounted but into what drive letter!?

like image 41
Tono Nam Avatar answered Sep 30 '22 15:09

Tono Nam