[C++ to C#] - Set drive partition as active.

Discussion in 'Mixed Languages' started by Josh Cell, Jun 18, 2013.

  1. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,171
    120
    #1 Josh Cell, Jun 18, 2013
    Last edited: Jun 19, 2013
    Well, I now need to make the partition as 'Active' for finish the boot module from the WinUSB Maker.

    The problem is: I need to support Windows XP, and the most obviously way was use the DISKPART, but Windows XP does not want to recognize USB Drives around that... :(

    I was looking around and we can do it using DeviceIoControl P/invoke around IoWrapper.dll from Win7 USB Tool from Microsoft.

    This DLL is unmanaged and I understand ZERO from Visual C++. I need of help now.

    I want to do it natively from C#. Can anyone understand these C++ code and able to convert to C# method?

    The source of the IoWrapper.dll are above, some that solve the problem here from :

    SOLVED:

    ********************************************************************************************

    http://forums.mydigitallife.net/thr...tion-as-active?p=765292&viewfull=1#post765411

    ********************************************************************************************

    .....
     

    Attached Files:

    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. Muerto

    Muerto MDL Debugger

    Mar 7, 2012
    1,858
    2,115
    60
    #2 Muerto, Jun 18, 2013
    Last edited by a moderator: Apr 20, 2017
    Maybe you can work from this?

    Code:
    private int SetActivePartition(string selectedDrive)
    {
        int hr = S_OK;
        int bSuccess = 0;
        uint dwBytesReturned = 0;
    
        System.IntPtr hDisk = OpenDiskHandle(selectedDrive);
        if (hDisk == null || INVALID_HANDLE_VALUE == hDisk)
        {
            hr = GetLastError();
            ExitOnFailure(hr, "Unable to get handle to disk.");
        }
    
        // Get the partition information
        byte[] Buffer = new byte[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3 * sizeof(PARTITION_INFORMATION_EX)];
        bSuccess = DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, null, 0, Buffer, sizeof(byte), dwBytesReturned, null);
    
        if (bSuccess == 0 || dwBytesReturned != sizeof(byte))
        {
            hr = GetLastError();
            ExitOnFailure(hr, "Unable to read partition information.");
        }
    
        // Set bootable flag and rewrite the partition if needed.
        DRIVE_LAYOUT_INFORMATION_EX pDriveLayout = (DRIVE_LAYOUT_INFORMATION_EX)Buffer;
        if (!pDriveLayout.PartitionEntry[0].Mbr.BootIndicator)
        {
            pDriveLayout.PartitionEntry[0].Mbr.BootIndicator = 1;
            pDriveLayout.PartitionEntry[0].RewritePartition = 1;
    
            bSuccess = DeviceIoControl(hDisk, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, pDriveLayout, sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3 * sizeof(PARTITION_INFORMATION_EX), null, 0, dwBytesReturned, null);
    
            if (bSuccess == 0)
            {
                hr = GetLastError();
                ExitOnFailure(hr, "Unable to write partition information.");
            }
        }
    
    LExit:
        if (null != hDisk && INVALID_HANDLE_VALUE != hDisk)
        {
            CloseHandle(hDisk);
        }
    
        return hr;
    Code:
    private System.IntPtr OpenDiskHandle(string rootPath)
    {
        int hr;
        System.IntPtr hDisk = INVALID_HANDLE_VALUE;
        string drivePath = null;
    
        // CreateFile requires a file name in the format '\\.\X:' instead of 'X:\'
        hr = StrAllocString(drivePath, "\\\\.\\", 6);
        ExitOnFailure(hr, "Unable to allocate drive path string.");
    
        hr = StrAllocConcat(drivePath, rootPath, 2);
        ExitOnFailure(hr, "Unable to concatenate drive path string.");
    
        // Open handle to disk
        hDisk = CreateFile(drivePath, GENERIC_EXECUTE | GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, null);
    
    LExit:
        ReleaseNullStr(drivePath);
    
        if (hr != S_OK)
        {
            SetLastError(hr);
        }
    
        return hDisk;
    }
     
  3. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,171
    120
    @The Dev

    I also have converted some code to C# using a tool but I can not understand some hard things that has many structs, enums.....
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,171
    120
    #4 Josh Cell, Jun 18, 2013
    Last edited: Jun 19, 2013
    (OP)
    I have found this class around MSDN blog:

    SOLVED:

    ********************************************************************************************

    http://forums.mydigitallife.net/thr...tion-as-active?p=765292&viewfull=1#post765411

    ********************************************************************************************

    It now are looking a bit easier, I will try to pass the correct flags and see if it will work...
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,171
    120
    #5 Josh Cell, Jun 18, 2013
    Last edited: Jun 19, 2013
    (OP)
    I have worked a bit but still it is not working:

    SOLVED:


    ************************************************** ******************************************

    http://forums.mydigitallife.net/thr...tion-as-active?p=765411&viewfull=1#post765411

    ************************************************** ******************************************

    It runs fine but no change around the partition (is not setting up to Active)....

    Any ideas?
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,171
    120
    #6 Josh Cell, Jun 19, 2013
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Ok guys, I have worked some hours today and here is the method working as well:

    Code:
            /*
    
             * IOWrapper C# class by Michel Oliveira.
             * 2013/06/18
             * www.joshcellsoftwares.com 
             
             GPL License.
             
             */
    
    namespace PartitionWrapper
    {
        using System;
        using System.Diagnostics;
        using System.Windows.Forms;
        using System.Runtime.InteropServices;
    
        public class IOWrapper
        {
            public static bool SetActivePartition(string selectedDrive)
            {
                bool RetCode = false;
    
                try
                {
                    bool bSuccess = false;
                    uint dwBytesReturned = 0;
    
                    IntPtr hDisk = OpenVolume(selectedDrive);
                    if (hDisk == null || hDisk == FSConstants.INVALID_HANDLE_VALUE)
                    {
                        RetCode = false;
                        goto FINAL;
                    }
    
                    // Get the partition information
                    uint PartitionInfomations = (uint)(Marshal.SizeOf(typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX)) + 3 * Marshal.SizeOf(typeof(FSStructures.PARTITION_INFORMATION_EX)));
                    byte[] DBuffer = new byte[PartitionInfomations];
    
                    GCHandle handle = GCHandle.Alloc(DBuffer, GCHandleType.Pinned);
    
                    FSStructures.DRIVE_LAYOUT_INFORMATION_EX pDriveLayout = (FSStructures.DRIVE_LAYOUT_INFORMATION_EX)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX));
    
                    IntPtr pDriveLayoutPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pDriveLayout));
    
                    Marshal.StructureToPtr(pDriveLayout, pDriveLayoutPtr, false);
    
                    bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_GET_DRIVE_LAYOUT_EX, default(IntPtr), default(uint), pDriveLayoutPtr, PartitionInfomations, ref dwBytesReturned);
    
                    pDriveLayout = (FSStructures.DRIVE_LAYOUT_INFORMATION_EX)Marshal.PtrToStructure(pDriveLayoutPtr, typeof(FSStructures.DRIVE_LAYOUT_INFORMATION_EX));
    
                    if (bSuccess || dwBytesReturned != PartitionInfomations)
                    {
                        RetCode = true;
                    }
                    else { RetCode = false; goto FINAL; }
    
                    if (!pDriveLayout.PartitionEntry[0].Mbr.BootIndicator)
                    {
                        pDriveLayout.PartitionEntry[0].PartitionStyle = FSStructures.PARTITION_STYLE.MasterBootRecord;
                        pDriveLayout.PartitionEntry[0].Mbr.BootIndicator = true;
                        pDriveLayout.PartitionEntry[0].RewritePartition = true;
                        {
                            pDriveLayoutPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pDriveLayout));
                            Marshal.StructureToPtr(pDriveLayout, pDriveLayoutPtr, false);
                        }
                        bSuccess = FSStructures.DeviceIoControl(hDisk, FSConstants.IOCTL_DISK_SET_DRIVE_LAYOUT_EX, pDriveLayoutPtr, PartitionInfomations, default(IntPtr), default(uint), ref dwBytesReturned);
                        if (bSuccess)
                        {
                            RetCode = true;
                        }
                        else { RetCode = false; }
                    }
    
                FINAL:
    
                    // Close the disk handle.
                    if (hDisk != null && hDisk != FSConstants.INVALID_HANDLE_VALUE)
                    {
                        FSStructures.CloseHandle(hDisk);
                    }
                }
                catch { return false; }
    
                return RetCode;
            }
    
            private static IntPtr OpenVolume(string DeviceName)
            {
                try
                {
                    IntPtr hDevice;
                    hDevice = FSStructures.CreateFile(
                        @"\\.\" + DeviceName,
                        FSConstants.GENERIC_EXECUTE | FSConstants.GENERIC_READ | FSConstants.GENERIC_WRITE | FSConstants.FILE_SHARE_READ | FSConstants.FILE_SHARE_WRITE,
                        FSConstants.FILE_SHARE_WRITE,
                        IntPtr.Zero,
                        FSConstants.OPEN_EXISTING,
                        0,
                        IntPtr.Zero);
    
    
                    if ((int)hDevice == -1)
                    {
                        throw new Exception(Marshal.GetLastWin32Error().ToString());
                    }
    
                    return hDevice;
                }
                catch { return FSConstants.INVALID_HANDLE_VALUE; }
            }
    
            internal static class FSConstants
            {
                public const uint FILE_SHARE_READ = 0x00000001;
                public const uint FILE_SHARE_WRITE = 0x00000002;
                public const uint OPEN_EXISTING = 3;
                public const int GENERIC_EXECUTE = 0x10000000;
    
                public const uint GENERIC_READ = (0x80000000);
                public const uint GENERIC_WRITE = (0x40000000);
    
                public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    
                public const uint IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x00070050;
    
                public const uint IOCTL_DISK_SET_DRIVE_LAYOUT_EX = 0x7C054;
            }
    
            internal static class FSStructures
            {
    
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern IntPtr CreateFile(
                    string lpFileName,
                    uint dwDesiredAccess,
                    uint dwShareMode,
                    IntPtr lpSecurityAttributes,
                    uint dwCreationDisposition,
                    uint dwFlagsAndAttributes,
                    IntPtr hTemplateFile);
    
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern int CloseHandle(IntPtr hObject);
    
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern bool DeviceIoControl(
                    IntPtr hDevice,
                    uint dwIoControlCode,
                    [Optional] IntPtr lpInBuffer,
                    uint nInBufferSize,
                    [Optional] [Out] IntPtr lpOutBuffer,
                    uint nOutBufferSize,
                    [Optional] ref uint lpBytesReturned,
                    [Optional] IntPtr lpOverlapped);
    
    
                [StructLayout(LayoutKind.Sequential)]
                public struct DRIVE_LAYOUT_INFORMATION_EX
                {
                    public PARTITION_STYLE PartitionStyle;
    
                    public int PartitionCount;
    
                    public DRIVE_LAYOUT_INFORMATION_UNION DriveLayoutInformatiton;
    
                    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 0x16)]
                    public PARTITION_INFORMATION_EX[] PartitionEntry;
                }
    
                [StructLayout(LayoutKind.Sequential)]
                public struct PARTITION_INFORMATION_EX
                {
                    [MarshalAs(UnmanagedType.U4)]
                    public PARTITION_STYLE PartitionStyle;
                    public long StartingOffset;
                    public long PartitionLength;
                    public int PartitionNumber;
                    public bool RewritePartition;
                    public PARTITION_INFORMATION_MBR Mbr;
                    public PARTITION_INFORMATION_GPT Gpt;
                }
    
                [StructLayout(LayoutKind.Sequential)]
                public struct PARTITION_INFORMATION_MBR
                {
                    public byte PartitionType;
                    [MarshalAs(UnmanagedType.U1)]
                    public bool BootIndicator;
                    [MarshalAs(UnmanagedType.U1)]
                    public bool RecognizedPartition;
                    public uint HiddenSectors;
                }
    
    
                [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
                public struct PARTITION_INFORMATION_GPT
                {
                    public Guid PartitionType;
                    public Guid PartitionId;
                    [MarshalAs(UnmanagedType.U8)]
                    public EFIPartitionAttributes Attributes;
    
                    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
                    public string Name;
                }
    
                [Flags]
                public enum EFIPartitionAttributes : ulong
                {
                    GPT_ATTRIBUTE_PLATFORM_REQUIRED = 0x0000000000000001,
                    LegacyBIOSBootable = 0x0000000000000004,
                    GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER = 0x8000000000000000,
                    GPT_BASIC_DATA_ATTRIBUTE_HIDDEN = 0x4000000000000000,
                    GPT_BASIC_DATA_ATTRIBUTE_SHADOW_COPY = 0x2000000000000000,
                    GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY = 0x1000000000000000
                }
    
    
                [StructLayout(LayoutKind.Explicit)]
                public struct DRIVE_LAYOUT_INFORMATION_UNION
                {
                    [FieldOffset(0)]
                    public DRIVE_LAYOUT_INFORMATION_MBR Mbr;
    
                    [FieldOffset(0)]
                    public DRIVE_LAYOUT_INFORMATION_GPT Gpt;
                }
    
                [StructLayout(LayoutKind.Sequential)]
                public struct DRIVE_LAYOUT_INFORMATION_GPT
                {
    
                    public Guid DiskId;
    
                    public long StartingUsableOffset;
    
                    public long UsableLength;
    
                    public int MaxPartitionCount;
                }
    
                [StructLayout(LayoutKind.Sequential)]
                public struct DRIVE_LAYOUT_INFORMATION_MBR
                {
                    public uint Signature;
                }
    
                public enum PARTITION_STYLE : int
                {
                    MasterBootRecord = 0,
                    GuidPartitionTable = 1,
                    Raw = 2
                }
            }
        }
    }
    USAGE:

    Code:
    PartitionWrapper.IOWrapper.SetActivePartition("K:"); //Where K: is your partition to make as active.
    I hope it will solve that. There is no solid method like that around the internet for .NET languages...

    See you soon.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  7. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,223
    22,281
    210