C# 通过使用TrueCrypt的驱动程序而不是命令提示符来自动化TrueCrypt

C# 通过使用TrueCrypt的驱动程序而不是命令提示符来自动化TrueCrypt,c#,driver,truecrypt,C#,Driver,Truecrypt,如果我想查看使用c#装载的所有卷,那么我必须查询true crypt驱动程序,因为我无法向TrueCrypt.exe发送命令以返回该信息 因此,如果我想查看所有已装入的卷以及它们装入的驱动器,我将调用TrueCryptHelper.GetMountedVolumes(): 代码如下: public static class TrueCryptHelper { public static Dictionary<char, string> GetMountedVolumes()

如果我想查看使用c#装载的所有卷,那么我必须查询true crypt驱动程序,因为我无法向TrueCrypt.exe发送命令以返回该信息

因此,如果我想查看所有已装入的卷以及它们装入的驱动器,我将调用
TrueCryptHelper.GetMountedVolumes()

代码如下:

public static class TrueCryptHelper
{
    public static Dictionary<char, string> GetMountedVolumes()
    {
        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_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);

        Dictionary<char, string> items = new Dictionary<char, string>();

        for (int i = 0; i < 26; i++)
        {
            string filePath = mount.wszVolume[i].ToString().Replace(@"\??\", "");
            if (filePath.Length > 2)
            {
                items[(char)('A' + i)] = filePath;
            }
            //Console.WriteLine("{0}: => {1}", (char)('A' + i), mount.wszVolume[i]);
        }

        return items;
    }

    private static readonly uint TC_GET_DRIVER_VERSION                      = (uint)CTL_CODE(0x00000022, 0x800 + (01), 0, 0);
    private static readonly uint TC_GET_BOOT_LOADER_VERSION                 = (uint)CTL_CODE(0x00000022, 0x800 + (02), 0, 0);
    private static readonly uint TC_MOUNT_VOLUME                            = (uint)CTL_CODE(0x00000022, 0x800 + (03), 0, 0);
    private static readonly uint TC_DISMOUNT_VOLUME                         = (uint)CTL_CODE(0x00000022, 0x800 + (04), 0, 0);
    private static readonly uint TC_DISMOUNT_ALL_VOLUMES                    = (uint)CTL_CODE(0x00000022, 0x800 + (05), 0, 0);
    private static readonly uint TC_GET_MOUNTED_VOLUMES                     = (uint)CTL_CODE(0x00000022, 0x800 + (06), 0, 0);
    private static readonly uint TC_GET_VOLUME_PROPERTIES                   = (uint)CTL_CODE(0x00000022, 0x800 + (07), 0, 0);
    private static readonly uint TC_GET_DEVICE_REFCOUNT                     = (uint)CTL_CODE(0x00000022, 0x800 + (08), 0, 0);
    private static readonly uint TC_WAS_REFERENCED_DEVICE_DELETED           = (uint)CTL_CODE(0x00000022, 0x800 + (09), 0, 0);
    private static readonly uint TC_IS_ANY_VOLUME_MOUNTED                   = (uint)CTL_CODE(0x00000022, 0x800 + (10), 0, 0);
    private static readonly uint TC_GET_PASSWORD_CACHE_STATUS               = (uint)CTL_CODE(0x00000022, 0x800 + (11), 0, 0);
    private static readonly uint TC_WIPE_PASSWORD_CACHE                     = (uint)CTL_CODE(0x00000022, 0x800 + (12), 0, 0);
    private static readonly uint TC_OPEN_TEST                               = (uint)CTL_CODE(0x00000022, 0x800 + (13), 0, 0);
    private static readonly uint TC_GET_DRIVE_PARTITION_INFO                = (uint)CTL_CODE(0x00000022, 0x800 + (14), 0, 0);
    private static readonly uint TC_GET_DRIVE_GEOMETRY                      = (uint)CTL_CODE(0x00000022, 0x800 + (15), 0, 0);
    private static readonly uint TC_PROBE_REAL_DRIVE_SIZE                   = (uint)CTL_CODE(0x00000022, 0x800 + (16), 0, 0);
    private static readonly uint TC_GET_RESOLVED_SYMLINK                    = (uint)CTL_CODE(0x00000022, 0x800 + (17), 0, 0);
    private static readonly uint TC_GET_BOOT_ENCRYPTION_STATUS              = (uint)CTL_CODE(0x00000022, 0x800 + (18), 0, 0);
    private static readonly uint TC_BOOT_ENCRYPTION_SETUP                   = (uint)CTL_CODE(0x00000022, 0x800 + (19), 0, 0);
    private static readonly uint TC_ABORT_BOOT_ENCRYPTION_SETUP             = (uint)CTL_CODE(0x00000022, 0x800 + (20), 0, 0);
    private static readonly uint TC_GET_BOOT_ENCRYPTION_SETUP_RESULT        = (uint)CTL_CODE(0x00000022, 0x800 + (21), 0, 0);
    private static readonly uint TC_GET_BOOT_DRIVE_VOLUME_PROPERTIES        = (uint)CTL_CODE(0x00000022, 0x800 + (22), 0, 0);
    private static readonly uint TC_REOPEN_BOOT_VOLUME_HEADER               = (uint)CTL_CODE(0x00000022, 0x800 + (23), 0, 0);
    private static readonly uint TC_GET_BOOT_ENCRYPTION_ALGORITHM_NAME      = (uint)CTL_CODE(0x00000022, 0x800 + (24), 0, 0);
    private static readonly uint TC_GET_PORTABLE_MODE_STATUS                = (uint)CTL_CODE(0x00000022, 0x800 + (25), 0, 0);
    private static readonly uint TC_SET_PORTABLE_MODE_STATUS                = (uint)CTL_CODE(0x00000022, 0x800 + (26), 0, 0);
    private static readonly uint TC_IS_HIDDEN_SYSTEM_RUNNING                = (uint)CTL_CODE(0x00000022, 0x800 + (27), 0, 0);
    private static readonly uint TC_GET_SYSTEM_DRIVE_CONFIG                 = (uint)CTL_CODE(0x00000022, 0x800 + (28), 0, 0);
    private static readonly uint TC_DISK_IS_WRITABLE                        = (uint)CTL_CODE(0x00000022, 0x800 + (29), 0, 0);
    private static readonly uint TC_START_DECOY_SYSTEM_WIPE                 = (uint)CTL_CODE(0x00000022, 0x800 + (30), 0, 0);
    private static readonly uint TC_ABORT_DECOY_SYSTEM_WIPE                 = (uint)CTL_CODE(0x00000022, 0x800 + (31), 0, 0);
    private static readonly uint TC_GET_DECOY_SYSTEM_WIPE_STATUS            = (uint)CTL_CODE(0x00000022, 0x800 + (32), 0, 0);
    private static readonly uint TC_GET_DECOY_SYSTEM_WIPE_RESULT            = (uint)CTL_CODE(0x00000022, 0x800 + (33), 0, 0);
    private static readonly uint TC_WRITE_BOOT_DRIVE_SECTOR                 = (uint)CTL_CODE(0x00000022, 0x800 + (34), 0, 0);
    private static readonly uint TC_IS_SYSTEM_FAVORITE_VOLUME_DIRTY         = (uint)CTL_CODE(0x00000022, 0x800 + (35), 0, 0);
    private static readonly uint TC_SET_SYSTEM_FAVORITE_VOLUME_DIRTY        = (uint)CTL_CODE(0x00000022, 0x800 + (36), 0, 0);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    private 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)]
    private 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');
        }
    }

    private static int CTL_CODE(int DeviceType, int Function, int Method, int Access)
    {
        return (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2)
          | (Method));
    }

    /// <summary>
    /// Sends a control code directly to a specified device driver, causing the corresponding device to perform the corresponding operation.
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
    /// </summary>        
    [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)]
    private 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);
}
公共静态类TrueCryptHelper
{
公共静态字典GetMountedVolumes()
{
uint size=(uint)Marshal.SizeOf(typeof(MOUNT_LIST_STRUCT));
IntPtr buffer=Marshal.AllocHGlobal((int)size);
uint字节返回;
IntPtr\u hdev=CreateFile(“\\.\\TrueCrypt”,FileAccess.ReadWrite,FileShare.ReadWrite,IntPtr.Zero,FileMode.Open,0,IntPtr.Zero);
bool-bResult=DeviceIoControl(\u hdev,TC\u GET\u MOUNTED\u volume,buffer,size,buffer,size,out bytesrurned,IntPtr.Zero);
MOUNT_LIST_STRUCT MOUNT=new MOUNT_LIST_STRUCT();
编组PTRTO结构(缓冲区、装载);
自由全球元帅(缓冲区);
字典项=新字典();
对于(int i=0;i<26;i++)
{
字符串filePath=mount.wszVolume[i].ToString().Replace(@“\??\”,“”);
如果(filePath.Length>2)
{
items[(char)('A'+i)]=文件路径;
}
//Console.WriteLine(“{0}:=>{1}”,(char)('A'+i),mount.wszVolume[i]);
}
退货项目;
}
专用静态只读uint TC_GET_DRIVER_VERSION=(uint)CTL_代码(0x00000022,0x800+(01),0,0);
私有静态只读uint TC\U GET\U BOOT\U LOADER\U版本=(uint)CTL\U代码(0x00000022,0x800+(02),0,0);
专用静态只读uint TC_MOUNT_VOLUME=(uint)CTL_代码(0x00000022,0x800+(03),0,0);
专用静态只读uint TC_卸除_卷=(uint)CTL_代码(0x00000022,0x800+(04),0,0);
专用静态只读uint TC_DISMOUNT_ALL_VOLUMES=(uint)CTL_代码(0x00000022,0x800+(05),0,0);
专用静态只读uint TC_GET_MOUNTED_VOLUMES=(uint)CTL_代码(0x00000022,0x800+(06),0,0);
私有静态只读uint TC_GET_VOLUME_PROPERTIES=(uint)CTL_代码(0x00000022,0x800+(07),0,0);
专用静态只读uint TC_GET_DEVICE_REFCOUNT=(uint)CTL_代码(0x00000022,0x800+(08),0,0);
专用静态只读uint TC_已被引用_设备_已删除=(uint)CTL_代码(0x00000022,0x800+(09),0,0);
私有静态只读uint TC_是任何已装入的卷=(uint)CTL_代码(0x00000022,0x800+(10),0,0);
私有静态只读uint TC_GET_PASSWORD_CACHE_STATUS=(uint)CTL_代码(0x00000022,0x800+(11),0,0);
专用静态只读uint TC_擦除_密码_缓存=(uint)CTL_代码(0x00000022,0x800+(12),0,0);
专用静态只读uint TC_OPEN_测试=(uint)CTL_代码(0x00000022,0x800+(13),0,0);
私有静态只读uint TC\U GET\U驱动器\U分区\U信息=(uint)CTL\U代码(0x00000022,0x800+(14),0,0);
专用静态只读uint TC_GET_DRIVE_GEOMETRY=(uint)CTL_代码(0x00000022,0x800+(15),0,0);
专用静态只读uint TC_PROBE_REAL_DRIVE_SIZE=(uint)CTL_代码(0x00000022,0x800+(16),0,0);
私有静态只读uint TC_GET_RESOLVED_SYMLINK=(uint)CTL_代码(0x00000022,0x800+(17),0,0);
私有静态只读uint TC\U GET\U BOOT\U ENCRYPTION\U STATUS=(uint)CTL\U代码(0x00000022,0x800+(18),0,0);
专用静态只读uint TC_引导_加密_设置=(uint)CTL_代码(0x00000022,0x800+(19),0,0);
专用静态只读uint TC_中止_启动_加密_设置=(uint)CTL_代码(0x00000022,0x800+(20),0,0);
私有静态只读uint TC\U GET\U BOOT\U ENCRYPTION\U SETUP\U RESULT=(uint)CTL\U代码(0x00000022,0x800+(21),0,0);
专用静态只读uint TC\u GET\u BOOT\u DRIVE\u VOLUME\u PROPERTIES=(uint)CTL\u代码(0x00000022,0x800+(22),0,0);
专用静态只读uint TC_重新打开_引导_卷头=(uint)CTL_代码(0x00000022,0x800+(23),0,0);
私有静态只读uint TC\U GET\U BOOT\U加密算法\U NAME=(uint)CTL\U代码(0x00000022,0x800+(24),0,0);
专用静态只读uint TC\U GET\U便携式模式\U状态=(uint)控制代码(0x00000022,0x800+(25),0,0);
专用静态只读uint TC_SET_PORTABLE_MODE_STATUS=(uint)CTL_代码(0x00000022,0x800+(26),0,0);
私有静态只读uint TC_是隐藏的系统_正在运行=(uint)CTL_代码(0x00000022,0x800+(27),0,0);
专用静态只读uint TC\U GET\U系统驱动器配置=(uint)控制代码(0x00000022,0x800+(28),0,0);
私有静态只读uint TC_DISK_可写=(uint)CTL_代码(0x00000022,0x800+(29),0,0);
专用静态只读uint TC_启动_诱饵_系统_擦除=(uint)控制代码(0x00000022,0x800+(30),0,0);
专用静态只读uint TC_中止_诱饵_系统_擦除=(uint)控制代码(0x00000022,0x800+(31),0,0);
专用静态只读uint TC\U GET\U DECOY\U SYSTEM\U WIPE\U STATUS=(uint)控制代码(0x00000022,0x800+(32),0,0);
专用静态只读uint TC\U GET\U DECOY\U SYSTEM\U WIPE\U RESULT=(uint)CTL\U代码(0x00000022,0x800+(33),0,0);
专用静态只读uint TC_WRITE_BOOT_DRIVE_SECTOR=(uint)CTL_代码(0x00000022,0x800+(34),0,0);
私有静态只读uint TC_是系统_收藏夹_卷_脏=(uint)CTL_代码(0x00000022,0x800+(35),0,0);
专用静态只读uint TC\u集合\u系统\u收藏夹
// Use only cached passwords if password = NULL
//
// Returns:
// -1 = user aborted mount / error
// 0  = mount failed
// 1  = mount OK
// 2  = mount OK in shared mode
//
// Note that some code calling this relies on the content of the mountOptions struct
// to remain unmodified (don't remove the 'const' without proper revision).

int MountVolume (HWND hwndDlg,
                 int driveNo,
                 char *volumePath,
                 Password *password,
                 BOOL cachePassword,
                 BOOL sharedAccess,
                 const MountOptions* const mountOptions,
                 BOOL quiet,
                 BOOL bReportWrongPassword)
MOUNT_STRUCT mount;



typedef struct
{
    int nReturnCode;                    /* Return code back from driver */
    BOOL FilesystemDirty;
    BOOL VolumeMountedReadOnlyAfterAccessDenied;
    BOOL VolumeMountedReadOnlyAfterDeviceWriteProtected;

    wchar_t wszVolume[TC_MAX_PATH];     /* Volume to be mounted */
    Password VolumePassword;            /* User password */
    BOOL bCache;                        /* Cache passwords in driver */
    int nDosDriveNo;                    /* Drive number to mount */
    uint32 BytesPerSector;
    BOOL bMountReadOnly;                /* Mount volume in read-only mode */
    BOOL bMountRemovable;               /* Mount volume as removable media */
    BOOL bExclusiveAccess;              /* Open host file/device in exclusive access mode */
    BOOL bMountManager;                 /* Announce volume to mount manager */
    BOOL bPreserveTimestamp;            /* Preserve file container timestamp */
    BOOL bPartitionInInactiveSysEncScope;       /* If TRUE, we are to attempt to mount a partition located on an encrypted system drive without pre-boot authentication. */
    int nPartitionInInactiveSysEncScopeDriveNo; /* If bPartitionInInactiveSysEncScope is TRUE, this contains the drive number of the system drive on which the partition is located. */
    BOOL SystemFavorite;
    // Hidden volume protection
    BOOL bProtectHiddenVolume;          /* TRUE if the user wants the hidden volume within this volume to be protected against being overwritten (damaged) */
    Password ProtectedHidVolPassword;   /* Password to the hidden volume to be protected against overwriting */
    BOOL UseBackupHeader;
    BOOL RecoveryMode;
} MOUNT_STRUCT;
bResult = DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, &mount,
        sizeof (mount), &mount, sizeof (mount), &dwResult, NULL);
truecrypt /v myvolume.tc /lx /a /p MyPassword /e /b
Public Sub Main()
    ' Instantiate the TrueCrypt Driver API
    Dim Driver As New TC_Driver("C:\truecrypt.sys") ' Or wherever the compiled TrueCrypt driver exists on your system

End Sub
Public Class TC_Driver
    Implements IDisposable

    Const CURRENT_VER As Integer = &H71A

    Private pDriver32bitLocation As String
    Private pDriver64bitLocation As String
    Private pIsPortableMode As Boolean = False

    Private Property ManagedDriver As ManagedDriver
    Private DriverSetupMutex As Mutex

    Public Sub New(ByVal DriverLocation64bit As String)
        'Checks for 64-bit OS. Currently x64 is the only supported platform
        If Not Environment.Is64BitProcess = Environment.Is64BitOperatingSystem Then
           Throw New PlatformNotSupportedException("TrueCryptAPI needs a 64 bit process to run correctly")
        End If

        ' Set the driver location as specified by DriverLocation64bit
        pDriver64bitLocation = Path.GetFullPath(DriverLocation64bit)

        Dim DriverStatus As TC_ERROR
        Dim DriverLoadAttempts As Integer = 0

        'Load the driver as a service using internal code
        ManagedDriver = New ManagedDriver

        'Attempt to Start the driver, fail with error after 3 attempts
        Do
          DriverStatus = StartDriver()
          DriverLoadAttempts += 1
        Loop While DriverStatus = TC_ERROR.FILES_OPEN_LOCK AndAlso DriverLoadAttempts < 3

        If DriverStatus <> TC_ERROR.SUCCESS Then
          Me.Dispose()
          Throw New ArgumentException("Driver not loaded. Error:" & DriverStatus)
        End If
    End Sub
'....
End Class
Public Sub Main()
    ' Instantiate the TrueCrypt Driver API
    Dim Driver As New TC_Driver("C:\truecrypt.sys") ' Or wherever the compiled TrueCrypt driver exists on your system

    Dim MyOptions As New MOUNT_OPTIONS With {.Removable = True}
    Driver.MountContainer("C:\MyTrueCryptContainer","S","SuperSecurePassword",MyOptions)

End Sub
    Public Structure MOUNT_OPTIONS
        Dim [ReadOnly] As Boolean
        Dim Removable As Boolean
        Dim ProtectHiddenVolume As Boolean
        Dim PreserveTimestamp As Boolean
        Dim PartitionInInactiveSysEncScope As Boolean
        Dim ProtectedHidVolPassword As Password
        Dim UseBackupHeader As Boolean
        Dim RecoveryMode As Boolean
    End Structure
Public Function MountContainer(ByVal FileName As String, ByVal DriveLetter As Char, ByVal Password As Password, ByVal Options As MOUNT_OPTIONS) As TC_ERROR
    Dim status As Boolean = False
    Dim mounted As TC_ERROR
    Dim tmp As String = ""

    'Apply the keyfile to the password
    If Not Password.ApplyKeyFile(tmp) Then Return False

    'Attempt to mount the volume using translated TrueCrypt methods
    mounted = MountVolume(Asc(DriveLetter) - Asc("A"), FileName, tmp, False, False, Options, False)

    tmp = ""
    Options.ProtectedHidVolPassword = Nothing

    Return mounted
End Function
Partial Public Class TC_Driver

Friend Function MountVolume(ByVal driveNo As Integer, ByVal volumePath As String, ByVal password As String, ByVal cachePassword As Boolean, ByVal sharedAccess As Boolean, ByRef MountOption As MOUNT_OPTIONS, ByVal quiet As Boolean) As TC_ERROR
    Dim mount As MOUNT_STRUCT
    Dim dwResult As UInteger
    Dim bResult As Boolean, bDevice As Boolean
    Dim favoriteMountOnArrivalRetryCount As Integer = 0

    If IsMountedVolume(volumePath) Then Return TC_ERROR.VOL_ALREADY_MOUNTED
    If Not VolumePathExists(volumePath) Then Return TC_ERROR.FILES_OPEN

    mount = New MOUNT_STRUCT
    mount.VolumePassword = New PASSWORD_STUCT
    mount.ProtectedHidVolPassword = New PASSWORD_STUCT

    mount.bExclusiveAccess = Not sharedAccess
    mount.SystemFavorite = False
    mount.UseBackupHeader = MountOption.UseBackupHeader
    mount.RecoveryMode = MountOption.RecoveryMode

retry:
    mount.nDosDriveNo = driveNo
    mount.bCache = cachePassword

    mount.bPartitionInInactiveSysEncScope = False

    If StringLen(password) > 0 Then
        mount.VolumePassword = New PASSWORD_STUCT

        mount.VolumePassword.Text = password.PadRight(MAX_PASSWORD + 1, Chr(0))
        mount.VolumePassword.Length = StringLen(password)
        mount.VolumePassword.Pad = "".PadRight(3, Chr(0))
    Else
        mount.VolumePassword = New PASSWORD_STUCT

        mount.VolumePassword.Text = "".PadRight(MAX_PASSWORD + 1, Chr(0))
        mount.VolumePassword.Length = 0
        mount.VolumePassword.Pad = "".PadRight(3, Chr(0))
    End If

    If (Not MountOption.ReadOnly) And MountOption.ProtectHiddenVolume Then
        mount.ProtectedHidVolPassword = New PASSWORD_STUCT

        mount.ProtectedHidVolPassword.Pad = "".PadRight(3, Chr(0))

        MountOption.ProtectedHidVolPassword.ApplyKeyFile(mount.ProtectedHidVolPassword.Text)
        mount.ProtectedHidVolPassword.Length = StringLen(mount.ProtectedHidVolPassword.Text)

        mount.bProtectHiddenVolume = True
    Else
        mount.ProtectedHidVolPassword = New PASSWORD_STUCT
        mount.ProtectedHidVolPassword.Length = 0
        mount.ProtectedHidVolPassword.Text = "".PadRight(MAX_PASSWORD + 1, Chr(0))
        mount.ProtectedHidVolPassword.Pad = "".PadRight(3, Chr(0))

        mount.bProtectHiddenVolume = False
    End If

    mount.bMountReadOnly = MountOption.ReadOnly
    mount.bMountRemovable = MountOption.Removable
    mount.bPreserveTimestamp = MountOption.PreserveTimestamp

    mount.bMountManager = True

    If volumePath.Contains("\\?\") Then volumePath = volumePath.Substring(4)

    If volumePath.Contains("Volume{") And volumePath.LastIndexOf("}\") = volumePath.Length - 2 Then
        Dim resolvedPath As String = VolumeGuidPathToDevicePath(volumePath)

        If Not resolvedPath = "" Then volumePath = resolvedPath
    End If

    mount.wszVolume = volumePath.PadRight(TC_MAX_PATH, Chr(0))

    If Not bDevice Then
        'UNC
        If volumePath.StartsWith("\\") Then
            'Bla bla
        End If

        Dim bps As UInteger, flags As UInteger, d As UInteger
        If GetDiskFreeSpace(Path.GetPathRoot(volumePath), d, bps, d, d) Then
            mount.BytesPerSector = bps
        End If

        If (Not mount.bMountReadOnly) And GetVolumeInformation(Path.GetPathRoot(volumePath), Nothing, 0, Nothing, d, flags, Nothing, 0) Then
            mount.bMountReadOnly = Not (flags And FILE_READ_ONLY_VOLUME) = 0
        End If
    End If

    bResult = DeviceIoControlMount(ManagedDriver.hDriver, TC_IOCTL.MOUNT_VOLUME, mount, Marshal.SizeOf(mount), mount, Marshal.SizeOf(mount), dwResult, Nothing)

    mount.VolumePassword = Nothing
    mount.ProtectedHidVolPassword = Nothing

    If Not bResult Then
        If Marshal.GetLastWin32Error = SYSTEM_ERROR.SHARING_VIOLATION Then
            'TODO

            If Not mount.bExclusiveAccess Then
                Return TC_ERROR.FILES_OPEN_LOCK
            Else
                mount.bExclusiveAccess = False
                GoTo retry
            End If

            Return TC_ERROR.ACCESS_DENIED
        End If

        Return TC_ERROR.GENERIC
    End If

    If Not mount.nReturnCode = 0 Then Return mount.nReturnCode

    'Mount successful
    BroadcastDeviceChange(DBT_DEVICE.ARRIVAL, driveNo, 0)

    If Not mount.bExclusiveAccess Then Return TC_ERROR.OUTOFMEMORY

    Return mount.nReturnCode
End Function