Eterlogic Virtual Drive SDK documentation


C# File/RAM disk (COM interface)

This is a C# code sample that creates disk 'Z' (file or RAM disk) implementing IVirtualDriveHandler2 COM interface.

You should use managed languages very carefully in callback handlers.
It is very important to understand that virtual drive callback handler 
behavior must be predictable. Implementation code must be short and efficient.

sharp.PNG

When creating new project, please note:

Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace VDSDK_Test
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Form1.cs

/* 
 * Simple VDSDK virtual disk implementation
 * (c) 2008-2009 Eterlogic.com. All rights reserved
 * MAIN FORM
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using VDSDKLib;


namespace VDSDK_Test
{
    public partial class Form1 : Form, VDSDKLib.IVirtualDriveFormatCallbackHandler
    {
        const int TYPE_RAM_DISK = 0;
        const int TYPE_FILE_DISK = 1;

        public Form1()
        {
            InitializeComponent();

            CreateBtn.Enabled = true;
            DestroyBtn.Enabled = false;
            FormatBtn.Enabled = false;
            comboDiskType.SelectedIndex = TYPE_RAM_DISK;

            progressBarFormat.Minimum = 0;
            progressBarFormat.Maximum = 100;

            m_driveHandle = -1;
            m_pHandler = null;

            // initialize VDSDK
            m_pManager = new VDSDKLib.VirtualDrivesManagerClass();
            m_pManager.InitializeVDSDK();


            // Activate VDSDK.
            // First parameter is activation key shipped with commercial license
            // In demo version this method always returns TRUE
            if (m_pManager.ActivateVDSDK("") == 0)
            {
                // Activation error
            }
        }

        ~Form1()
        {
        }


        private VirtualDiskHandler m_pHandler; // out virtual drive event handler
        private int m_driveHandle; // virtual drive handle
        private VDSDKLib.VirtualDrivesManagerClass m_pManager;

        public void OnFormatCallback(uint Progress)
        {
            progressBarFormat.Value = (int)Progress;
        }

        private void OnClickMount(object sender, EventArgs e)
        {
            uint diskSize = Convert.ToUInt32(textBoxDiskSize.Text);
            char diskLetter = textBoxDiskLetter.Text[0];

            int diskType = comboDiskType.SelectedIndex;
            switch(diskType)
            {
                case TYPE_RAM_DISK:
                    {
                        m_pHandler = new RamDiskHandler(diskSize);
                        break;
                    }
                case TYPE_FILE_DISK:
                    {
                        FileDiskHandler pFileDiskHandler = new FileDiskHandler("disk.dat");
                        m_pHandler = pFileDiskHandler;
                        // allocate physical space for our disk
                        pFileDiskHandler.PreAllocate(diskSize);
                        break;
                    }
            }

            if (checkBoxEncryption.Checked)
            {
                // Use simple encryption algorithm
                DES encryption = System.Security.Cryptography.DES.Create();
                int KeySize = encryption.KeySize / 8; // key size (in bytes)

                // Set encryption cipher mode
                encryption.Mode = CipherMode.ECB;

                // Disable padding (important)
                encryption.Padding = PaddingMode.None;

                // Generate hash by the entered password
                MD5CryptoServiceProvider hashProvider = new MD5CryptoServiceProvider();
                byte[] hash = hashProvider.ComputeHash(UTF8Encoding.UTF8.GetBytes(textBoxPassword.Text));
                byte[] encryptionKey = hash;

                // If hash is too long for our key, truncate it
                if (hash.Length > KeySize)
                {
                    encryptionKey = new byte[KeySize];
                    Buffer.BlockCopy(hash, 0, encryptionKey, 0, KeySize);
                }

                // Set encryption key
                encryption.Key = encryptionKey;
                m_pHandler.SetupEncryption(encryption);
            }


            m_driveHandle = m_pManager.CreateVirtualDrive((byte)diskLetter, diskSize, m_pHandler);
            if (m_driveHandle == -1)
            {
                m_pHandler = null;
                MessageBox.Show("Error");
                return;
            }


            CreateBtn.Enabled = false;
            DestroyBtn.Enabled = true;
            FormatBtn.Enabled = true;
        }


        private void UnmountDisk()
        {
            if (m_driveHandle != -1)
            {
                m_pManager.DestroyVirtualDrive(m_driveHandle, 1);
                m_pHandler.Release();
                m_pHandler = null;
                m_driveHandle = -1;

                CreateBtn.Enabled = true;
                DestroyBtn.Enabled = false;
                FormatBtn.Enabled = false;
                progressBarFormat.Value = 0;
            }
        }

        private void OnClickUnmount(object sender, EventArgs e)
        {
            UnmountDisk();
        }

        private void OnFormatCreate(object sender, EventArgs e)
        {
            // full format
            if(m_pManager.FormatVirtualDrive(m_driveHandle, 0, "NTFS", "VDSDK_DISK", this) == 1)
                MessageBox.Show("Success");
            else
                MessageBox.Show("Error");
        }

        private void OnClosing(object sender, FormClosingEventArgs e)
        {
            UnmountDisk();
            m_pManager.ShutdownVDSDK(1);
        }

        private void checkBoxEncryption_CheckedChanged(object sender, EventArgs e)
        {
            textBoxPassword.Enabled = checkBoxEncryption.Checked;
        }
    }
}

RamDiskHandler.cs

/* 
 * Simple VDSDK virtual disk implementation
 * (c) 2008-2009 Eterlogic.com. All rights reserved
 * RAM DISK handler
 */


using VDSDKLib;

namespace VDSDK_Test
{
    public class RamDiskHandler : VirtualDiskHandler
    {
        private byte[] m_buffer;
        public RamDiskHandler(uint size)
        {
            m_buffer = new byte[size * 1024 * 1024];
        }

        override public void Release()
        {
            m_buffer = null;
        }

        ~RamDiskHandler()
        {
            Release();
        }

        override protected uint OnReadDataImpl(System.UInt64 Offset, uint Size, out System.Array Buffer)
        {
            byte[] buf = new byte[Size];
            System.Array.Copy(m_buffer, (int)Offset, buf, 0, (int)Size);
            Buffer = buf;
            return Size;
        }

        override protected uint OnWriteDataImpl(System.UInt64 Offset, uint Size, ref System.Array Buffer)
        {
            System.Array.Copy((byte[])Buffer, 0, m_buffer, (int)Offset, (int)Size);
            return Size;
        }
    }
}

FileDiskHandler.cs

/* 
 * Simple VDSDK virtual disk implementation
 * (c) 2008-2009 Eterlogic.com. All rights reserved
 * FILE DISK handler
 */

using VDSDKLib;

namespace VDSDK_Test
{
    public class FileDiskHandler : VirtualDiskHandler
    {
        const uint FILE_SHARE_READ = 1;
        const uint GENERIC_READ = 0x80000000;
        const uint GENERIC_WRITE = 0x40000000;
        const uint OPEN_ALWAYS = 4;
        const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
        const uint FILE_FLAG_RANDOM_ACCESS = 0x10000000;
        const uint FILE_BEGIN = 0;

        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe System.IntPtr CreateFile
            (
            string FileName,
            uint DesiredAccess,
            uint ShareMode,
            uint SecurityAttributes,
            uint CreationDisposition,
            uint FlagsAndAttributes,
            int hTemplateFile
            );

        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool ReadFile
            (
            System.IntPtr hFile,
            void* pBuffer,
            uint NumberOfBytesToRead,
            uint* pNumberOfBytesRead,
            int Overlapped
            );


        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe uint GetFileSize
            (
            System.IntPtr hFile,
            uint* lpFileSizeHigh
            );


        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool WriteFile
            (
            System.IntPtr hFile,
            void* pBuffer,
            uint NumberOfBytesToWrite,
            uint* pNumberOfBytesWritten,
            int Overlapped
            );


        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool CloseHandle
            (
            System.IntPtr hObject
            );

        [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
        static extern unsafe bool SetFilePointer
            (
            System.IntPtr hObject,
            uint lDistanceToMove,
            uint* lpDistanceToMoveHigh,
            uint dwMoveMethod
            );




        // =============================
        // class methods and members
        // =============================

        System.IntPtr m_hFile;


        public FileDiskHandler(string path)
        {
            // create file with special attributes
            m_hFile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0,
                OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, 0);
        }

        override public void Release()
        {
            if (m_hFile != (System.IntPtr)(-1))
            {
                CloseHandle(m_hFile);
                m_hFile = (System.IntPtr)(-1);
            }
        }

        ~FileDiskHandler()
        {
            Release();
        }

        // preallocate file space
        public void PreAllocate(uint diskSizeInMB)
        {
            const int chunkSize = 8;
            byte[] buf = new byte[chunkSize * 1024 * 1024];
            unsafe
            {
                uint sz, szHigh;
                sz = GetFileSize(m_hFile, &szHigh);

                System.UInt64 size = sz;
                System.UInt64 sizeHigh = (szHigh << 32);
                size += sizeHigh;
                size /= (1024 * 1024);
                if (size == diskSizeInMB)
                    return;

                fixed (byte* p = buf)
                {
                    for (int i = 0; i < diskSizeInMB / chunkSize; ++i)
                    {
                        uint dw;
                        WriteFile(m_hFile, p, chunkSize * 1024 * 1024, &dw, 0);
                    }
                }
            }
        }

        override protected uint OnReadDataImpl(System.UInt64 Offset, uint Size, out System.Array Buffer)
        {
            uint result = 0;
            byte[] buf = new byte[Size];
            unsafe
            {
                fixed (byte* p = buf)
                {
                    uint low = (uint)(Offset & 0xffffffff);
                    uint high = (uint)(Offset >> 32);
                    SetFilePointer(m_hFile, low, &high, FILE_BEGIN);
                    ReadFile(m_hFile, p, Size, &result, 0);
                }
            }
            Buffer = buf;
            return Size;
        }

        override protected uint OnWriteDataImpl(System.UInt64 Offset, uint Size, ref System.Array Buffer)
        {
            uint result = 0;
            byte[] buf = (byte[])Buffer;
            unsafe
            {
                fixed (byte* p = buf)
                {
                    uint low = (uint)(Offset & 0xffffffff);
                    uint high = (uint)(Offset >> 32);
                    SetFilePointer(m_hFile, low, null, FILE_BEGIN);
                    WriteFile(m_hFile, p, Size, &result, 0);
                }
            }
            Buffer = buf;
            return result;
        }
    }
}

(C) 2008-2009 Eterlogic.com. All rights reserved.