Click here to Skip to main content
13,624,514 members
Click here to Skip to main content
Add your own
alternative version

Stats

2.5K views
50 downloads
3 bookmarked
Posted 23 Jun 2018
Licenced CPOL

Determining all bootable partitions

, 28 Jun 2018
Rate this:
Please Sign up or sign in to vote.
Determining all bootable partitions using PInvoke

Introduction

In this article, I will show how to determine boot partition of Windows OS with C# by using Win API (pinvoke).

Background

Windows OS has different types of partition on the disk. And there must be a system partition generally (C:\), other than this, there may be user partitions such as D: \, E:\. There may also be another type of partition such as Boot partition which is what constitutes the subject of our writing. Sometimes, developers want to identify boot partition in order not to damage the system because this partition is very important for boot operation of Windows OS.

Thanks to Richard, I realized boot indicator property is not valid on GPT disk. So I updated source code and article as compatible with GPT disk.

Using the Code

I used C# (Pinvoke). I have to define classic MS definitions which are structs, constants, etc. So I won't mention these definitions below.

The Native class contains definitions of structs, constants of Win API.

The NativeApi the class contains functions of Win API like,CreateFileDeviceIoControl  etc.

Firstly; We need to obtain handles of all hard drives which are mounted on the system. So we enumerate these drives. And then we can get partition list for all physical drives. Then we can enumerate all partitions.

This is full of body code:

  public const uint MAX_NUMBER_OF_DRIVES = 64;

  for (uint i = 0; i < MAX_NUMBER_OF_DRIVES; i++)
  {
     // try to open the current physical drive
     string volume = string.Format("\\\\.\\PhysicalDrive{0}", i); 
     SafeFileHandle hndl = CreateFile(volume, Native.GENERIC_READ | Native.GENERIC_WRITE,
                                                Native.FILE_SHARE_READ | Native.FILE_SHARE_WRITE,
                                                IntPtr.Zero,
                                                Native.OPEN_EXISTING,
                                                Native.FILE_ATTRIBUTE_READONLY,
                                                IntPtr.Zero);
     //We have got handle now.

     //Some necessary variables definitions
     IntPtr driveLayoutPtr = IntPtr.Zero;
     int DRIVE_LAYOUT_BUFFER_SIZE = 1024;
     int error;
     uint dummy = 0;
                
     do
     {
       error = 0;
       driveLayoutPtr = Marshal.AllocHGlobal(DRIVE_LAYOUT_BUFFER_SIZE);
       if (DeviceIoControl
          (hndl, Native.IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IntPtr.Zero, 0, driveLayoutPtr, 
          (uint)DRIVE_LAYOUT_BUFFER_SIZE, ref dummy, IntPtr.Zero))
          {
            // I/O-control has been invoked successfully, 
            //convert to DRIVE_LAYOUT_INFORMATION_EX
             DRIVE_LAYOUT_INFORMATION_EX driveLayout = (DRIVE_LAYOUT_INFORMATION_EX)
             Marshal.PtrToStructure(driveLayoutPtr, typeof(DRIVE_LAYOUT_INFORMATION_EX));
             //Now i have got partition
             for (uint p = 0; p < driveLayout.PartitionCount; p++)
             {
                //Enumerate partition by using pointer arithmetic
                IntPtr ptr = new IntPtr(driveLayoutPtr.ToInt64() + 
                Marshal.OffsetOf(typeof(DRIVE_LAYOUT_INFORMATION_EX), "PartitionEntry").ToInt64()
                + (p * Marshal.SizeOf(typeof(PARTITION_INFORMATION_EX))));

                PARTITION_INFORMATION_EX partInfo = (PARTITION_INFORMATION_EX)
                Marshal.PtrToStructure(ptr, typeof(PARTITION_INFORMATION_EX));
                //Check partition is recognized or not
               if (partInfo.PartitionStyle != PARTITION_STYLE.PARTITION_STYLE_GPT)
               {
                 if ((partInfo.PartitionStyle != PARTITION_STYLE.PARTITION_STYLE_MBR) || 
                     (partInfo.Mbr.RecognizedPartition))
                 {
                   if (partInfo.Mbr.BootIndicator == true)
                   {
                    Console.WriteLine("Drive No: " + i + " Partition Number :" + 
                                       partInfo.PartitionNumber + " is boot partition");

                   }

                 }
               }
               else if (partInfo.PartitionStyle == PARTITION_STYLE.PARTITION_STYLE_GPT) {
                 //e3c9e316-0b5c-4db8-817d-f92df00215ae guid is defined from MS here:
                 //https://msdn.microsoft.com/en-us/library/windows/desktop/aa365449(v=vs.85).aspx
                 if (partInfo.Gpt.PartitionType== new Guid("e3c9e316-0b5c-4db8-817d-f92df00215ae"))
                 {
                 Console.WriteLine("Drive No: " + i + " Partition Number :" 
                                  + partInfo.PartitionNumber + " is boot partition");


                 }
              }
             }
            }
       else
       {
          error = Marshal.GetLastWin32Error();
          DRIVE_LAYOUT_BUFFER_SIZE *= 2;                    
        }
       Marshal.FreeHGlobal(driveLayoutPtr);
       driveLayoutPtr = IntPtr.Zero;
  } while (error == Native.ERROR_INSUFFICIENT_BUFFER);
}

As seen above, we get all partitions and check each one is BootIndicator or not.

The important thing is at first, filling DRIVE_LAYOUT_INFORMATION_EX structure by using the DeviceIoControl function. And then there is pointer arithmetic to extract buffer. Finally, We need to convert byte buffer to the PARTITION_INFORMATION_EX structure. That's all!

Don't forget that boot partition doesn't have to be separated on all Windows installed machines. Consider that boot OS files may be on OS installed partition which is generally " Local Disk (C:) ".

Finally, if you want to test sample application, the application requires administrator credentials to run correctly.

 

Points of Interest

I wrote this article for developers which are interested in Win API programming. And I think low-level programming is very hard and interesting. So I like learning new things when I develop a program. I think if you are interested in learning fundamentals of something, then this topic will help you to identify boot partition programmatically. I hope you enjoyed reading this article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

hasan bozkurt
Software Developer (Senior) codepark software
Turkey Turkey
I m interested in C# ,Java,Delphi programming language.I developed many types program which are generally enterprise solution.I m also interested in security ,forensic,system software development,encryption,Windows services,network programming .I have a OOP and Desing Patterns book writing work.

You may also be interested in...

Comments and Discussions

 
BugWill Fail on system with multiple bootable drives Pin
Randor 23-Jun-18 22:27
professional Randor 23-Jun-18 22:27 
GeneralRe: Will Fail on system with multiple bootable drives Pin
hasan bozkurt23-Jun-18 22:53
memberhasan bozkurt23-Jun-18 22:53 
GeneralRe: Will Fail on system with multiple bootable drives Pin
Randor 23-Jun-18 23:09
professional Randor 23-Jun-18 23:09 
GeneralRe: Will Fail on system with multiple bootable drives Pin
hasan bozkurt24-Jun-18 10:56
memberhasan bozkurt24-Jun-18 10:56 
GeneralRe: Will Fail on system with multiple bootable drives Pin
Randor 24-Jun-18 14:12
professional Randor 24-Jun-18 14:12 
GeneralRe: Will Fail on system with multiple bootable drives Pin
hasan bozkurt25-Jun-18 0:17
memberhasan bozkurt25-Jun-18 0:17 
GeneralRe: Will Fail on system with multiple bootable drives Pin
Randor 25-Jun-18 4:15
professional Randor 25-Jun-18 4:15 
GeneralRe: Will Fail on system with multiple bootable drives Pin
hasan bozkurt25-Jun-18 23:00
memberhasan bozkurt25-Jun-18 23:00 
GeneralRe: Will Fail on system with multiple bootable drives Pin
Randor 26-Jun-18 5:17
professional Randor 26-Jun-18 5:17 
GeneralRe: Will Fail on system with multiple bootable drives Pin
hasan bozkurt26-Jun-18 8:03
memberhasan bozkurt26-Jun-18 8:03 
QuestionSomething wrong shirley ... Pin
Richard MacCutchan23-Jun-18 7:03
protectorRichard MacCutchan23-Jun-18 7:03 
AnswerRe: Something wrong shirley ... Pin
hasan bozkurt23-Jun-18 9:04
memberhasan bozkurt23-Jun-18 9:04 
GeneralRe: Something wrong shirley ... Pin
Richard MacCutchan23-Jun-18 9:47
protectorRichard MacCutchan23-Jun-18 9:47 
GeneralRe: Something wrong shirley ... Pin
hasan bozkurt23-Jun-18 10:35
memberhasan bozkurt23-Jun-18 10:35 
GeneralRe: Something wrong shirley ... Pin
hasan bozkurt23-Jun-18 12:08
memberhasan bozkurt23-Jun-18 12:08 
GeneralRe: Something wrong shirley ... Pin
Richard MacCutchan23-Jun-18 21:29
protectorRichard MacCutchan23-Jun-18 21:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02-2016 | 2.8.180712.1 | Last Updated 28 Jun 2018
Article Copyright 2018 by hasan bozkurt
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid