title: DeviceIoControl to initialize and create a NTFS partition
body: <p>I'm trying to initialize a disk and create a NTFS partition via DeviceIOControl, without using either DiskPart or WMI.</p>
  
  <p>Using the below code I'm able to initialize the disk and create a RAW partition, but I'm unable to tweak the parameters so that the new partition is NTFS.</p>
  
  <p>Any ideas?</p>
  
  <pre><code>//Returns true if drive Index is successfully created
  //Returns false if not created successfully
  public static bool CreatePartition(int driveIndex, string physicalName)
  {
      IntPtr handle = GetHandle(driveIndex, physicalName);
  
      if (handle == INVALID_HANDLE_VALUE)
      {
          return false;
      }
  
      //Step 2: IOCTL_DISK_GET_DRIVE_GEOMETRY_EX to get the physical disk's geometry ( we need some information in it to fill partition data)
      //The number of surfaces (or heads, which is the same thing), cylinders, and sectors vary a lot; the specification of the number of each is called the geometry of a hard disk. 
      //The geometry is usually stored in a special, battery-powered memory location called the CMOS RAM , from where the operating system can fetch it during bootup or driver initialization.
      int size = 0;
      DISK_GEOMETRY_EX geometry = new DISK_GEOMETRY_EX();
      IntPtr lpOutBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DISK_GEOMETRY_EX)));
      Marshal.StructureToPtr(geometry, lpOutBuffer, false);
      int result = DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, IntPtr.Zero, 0, lpOutBuffer, Marshal.SizeOf(typeof(DISK_GEOMETRY_EX)), ref size, IntPtr.Zero);
      geometry = (DISK_GEOMETRY_EX)Marshal.PtrToStructure(lpOutBuffer, typeof(DISK_GEOMETRY_EX));
  
  
      //Step 3: IOCTL_DISK_CREATE_DISK is used to initialize a disk with an empty partition table. 
      CREATE_DISK createDisk = new CREATE_DISK();
      createDisk.PartitionStyle = PARTITION_STYLE.PARTITION_STYLE_MBR;
      createDisk.Mbr.Signature = 1;
  
      IntPtr createDiskBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CREATE_DISK)));
      Marshal.StructureToPtr(createDisk, createDiskBuffer, false);
  
      byte[] arr1 = new byte[Marshal.SizeOf(typeof(CREATE_DISK))];
      Marshal.Copy(createDiskBuffer, arr1, 0, Marshal.SizeOf(typeof(CREATE_DISK)));
  
      result = DeviceIoControl(handle, IOCTL_DISK_CREATE_DISK, createDiskBuffer, Marshal.SizeOf(typeof(CREATE_DISK)),
                                  IntPtr.Zero, 0, ref size, IntPtr.Zero);
  
      result = DeviceIoControl(handle, IOCTL_DISK_UPDATE_PROPERTIES, IntPtr.Zero, 0, IntPtr.Zero, 0, ref size, IntPtr.Zero);
  
  
      //Step 4: IOCTL_DISK_SET_DRIVE_LAYOUT_EX to repartition a disk as specified.
      //Note: use IOCTL_DISK_UPDATE_PROPERTIES to synchronize system view after IOCTL_DISK_CREATE_DISK and IOCTL_DISK_SET_DRIVE_LAYOUT_EX
      /* DWORD driveLayoutSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 4 * 25;
          DRIVE_LAYOUT_INFORMATION_EX *DriveLayoutEx = (DRIVE_LAYOUT_INFORMATION_EX *) new BYTE[driveLayoutSize];*/
  
  
  
      IntPtr driveLayoutbuffer = Marshal.AllocHGlobal(192);
      FillMemory(driveLayoutbuffer, 192, 0);
      DRIVE_LAYOUT_INFORMATION_EX driveLayoutEx = new DRIVE_LAYOUT_INFORMATION_EX();
      driveLayoutEx.PartitionEntry = new PARTITION_INFORMATION_EX[1];
  
  
      mediaType = (int)geometry.Geometry.MediaType;
      Int64 bytes_per_track = (geometry.Geometry.SectorsPerTrack) * (geometry.Geometry.BytesPerSector);
  
      driveLayoutEx.PartitionEntry[0].StartingOffset = 0x0;
  
      Int64 main_part_size_in_sectors, extra_part_size_in_sectors = 0;
      main_part_size_in_sectors = (geometry.DiskSize - driveLayoutEx.PartitionEntry[0].StartingOffset) / geometry.Geometry.BytesPerSector;
  
      if (main_part_size_in_sectors &lt;= 0)
      {
          return false;
      }
  
      extra_part_size_in_sectors = (MIN_EXTRA_PART_SIZE + bytes_per_track - 1) / bytes_per_track;
      main_part_size_in_sectors = ((main_part_size_in_sectors / geometry.Geometry.SectorsPerTrack) -
                                      extra_part_size_in_sectors) * geometry.Geometry.SectorsPerTrack;
      if (main_part_size_in_sectors &lt;= 0)
      {
          return false;
      }
  
      driveLayoutEx.PartitionEntry[0].PartitionLength = 1024 * 1024 * 1024 * (long)20;
      driveLayoutEx.PartitionEntry[0].PartitionStyle = PARTITION_STYLE.PARTITION_STYLE_MBR;
      driveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x80;
      driveLayoutEx.PartitionEntry[0].Mbr.BootIndicator = true;
      driveLayoutEx.PartitionEntry[0].PartitionNumber = 1;
      driveLayoutEx.PartitionEntry[0].RewritePartition = true;
      driveLayoutEx.PartitionEntry[0].Mbr.RecognizedPartition = true;
  
  
      driveLayoutEx.PartitionStyle = PARTITION_STYLE.PARTITION_STYLE_MBR;
      driveLayoutEx.PartitionCount = 1; //It should be a multiple of 4
      driveLayoutEx.Mbr.Mbr.Signature = createDisk.Mbr.Signature;
      Marshal.StructureToPtr(driveLayoutEx, driveLayoutbuffer, false);
  
      result = DeviceIoControl(handle, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, driveLayoutbuffer, 192, IntPtr.Zero, 0, ref size, IntPtr.Zero);
      result = DeviceIoControl(handle, IOCTL_DISK_UPDATE_PROPERTIES, IntPtr.Zero, 0, IntPtr.Zero, 0, ref size, IntPtr.Zero);
  
      Marshal.FreeHGlobal(driveLayoutbuffer);
      Marshal.FreeHGlobal(createDiskBuffer);
  
      Marshal.FreeHGlobal(lpOutBuffer);
  
      return true;
  }
  
  [DllImport("kernel32.dll", SetLastError = true)]
  static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
      uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
      uint dwFlagsAndAttributes, IntPtr hTemplateFile);
  
  [DllImport("kernel32")]
  static extern int CloseHandle(IntPtr handle);
  
  
  [DllImport("kernel32")]
  private static extern int DeviceIoControl
      (IntPtr deviceHandle, uint ioControlCode,
          IntPtr inBuffer, int inBufferSize,
          IntPtr outBuffer, int outBufferSize,
          ref int bytesReturned, IntPtr overlapped);
  
  public const uint GENERIC_READ = 0x80000000;
  public const uint GENERIC_WRITE = 0x40000000;
  public const uint FILE_SHARE_READ = 0x00000001;
  public const uint FILE_SHARE_WRITE = 0x00000002;
  public const uint OPEN_EXISTING = 0x00000003;
  public const uint FILE_ATTRIBUTE_NORMAL = 0x80;
  public const uint FSCTL_ALLOW_EXTENDED_DASD_IO = 0x90083;
  public const int DRIVE_ACCESS_RETRIES = 10;
  public const int DRIVE_ACCESS_TIMEOUT = 15000;
  public const uint FSCTL_LOCK_VOLUME = 0x00090018;
  static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
  public const uint IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x00070050;
  public const uint IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = 0x000700A0;
  public const uint IOCTL_DISK_CREATE_DISK = 0x0007C058;
  public const uint IOCTL_DISK_UPDATE_PROPERTIES = 0x00070140;
  public const uint IOCTL_DISK_SET_DRIVE_LAYOUT_EX = 0x0007C054;
  public const int MIN_EXTRA_PART_SIZE = 1024 * 1024;
  public static int mediaType = 0;
  [DllImport("kernel32.dll", EntryPoint = "RtlFillMemory", SetLastError = false)]
  public static extern void FillMemory(IntPtr destination, uint length, byte fill);
  
  /// &lt;summary&gt;
  /// Describes the geometry of disk devices and media.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  public struct DISK_GEOMETRY
  {
      /// &lt;summary&gt;
      /// The number of cylinders.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public Int64 Cylinders;
  
      /// &lt;summary&gt;
      /// The type of media. For a list of values, see MEDIA_TYPE.
      /// &lt;/summary&gt;
      [FieldOffset(8)]
      public MEDIA_TYPE MediaType;
  
      /// &lt;summary&gt;
      /// The number of tracks per cylinder.
      /// &lt;/summary&gt;
      [FieldOffset(12)]
      public uint TracksPerCylinder;
  
      /// &lt;summary&gt;
      /// The number of sectors per track.
      /// &lt;/summary&gt;
      [FieldOffset(16)]
      public uint SectorsPerTrack;
  
      /// &lt;summary&gt;
      /// The number of bytes per sector.
      /// &lt;/summary&gt;
      [FieldOffset(20)]
      public uint BytesPerSector;
  }
  
  
  public enum MEDIA_TYPE
  {
      Unknown,                // Format is unknown
      F5_1Pt2_512,            // 5.25", 1.2MB,  512 bytes/sector
      F3_1Pt44_512,           // 3.5",  1.44MB, 512 bytes/sector
      F3_2Pt88_512,           // 3.5",  2.88MB, 512 bytes/sector
      F3_20Pt8_512,           // 3.5",  20.8MB, 512 bytes/sector
      F3_720_512,             // 3.5",  720KB,  512 bytes/sector
      F5_360_512,             // 5.25", 360KB,  512 bytes/sector
      F5_320_512,             // 5.25", 320KB,  512 bytes/sector
      F5_320_1024,            // 5.25", 320KB,  1024 bytes/sector
      F5_180_512,             // 5.25", 180KB,  512 bytes/sector
      F5_160_512,             // 5.25", 160KB,  512 bytes/sector
      RemovableMedia,         // Removable media other than floppy
      FixedMedia,             // Fixed hard disk media
      F3_120M_512,            // 3.5", 120M Floppy
      F3_640_512,             // 3.5" ,  640KB,  512 bytes/sector
      F5_640_512,             // 5.25",  640KB,  512 bytes/sector
      F5_720_512,             // 5.25",  720KB,  512 bytes/sector
      F3_1Pt2_512,            // 3.5" ,  1.2Mb,  512 bytes/sector
      F3_1Pt23_1024,          // 3.5" ,  1.23Mb, 1024 bytes/sector
      F5_1Pt23_1024,          // 5.25",  1.23MB, 1024 bytes/sector
      F3_128Mb_512,           // 3.5" MO 128Mb   512 bytes/sector
      F3_230Mb_512,           // 3.5" MO 230Mb   512 bytes/sector
      F8_256_128,             // 8",     256KB,  128 bytes/sector
      F3_200Mb_512,           // 3.5",   200M Floppy (HiFD)
      F3_240M_512,            // 3.5",   240Mb Floppy (HiFD)
      F3_32M_512              // 3.5",   32Mb Floppy
  }
  
  /// &lt;summary&gt;
  /// Describes the extended geometry of disk devices and media.
  /// &lt;/summary&gt;
      [StructLayout(LayoutKind.Explicit)]
  private struct DISK_GEOMETRY_EX
  {
      /// &lt;summary&gt;
      /// A DISK_GEOMETRY structure.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public DISK_GEOMETRY Geometry;
  
      /// &lt;summary&gt;
      /// The disk size, in bytes.
      /// &lt;/summary&gt;
      [FieldOffset(24)]
      public Int64 DiskSize;
  
      /// &lt;summary&gt;
      /// Any additional data.
      /// &lt;/summary&gt;
      [FieldOffset(32)]
      public Byte Data;
  }
  
  
  
  /// &lt;summary&gt;
  /// Represents the format of a partition.
  /// &lt;/summary&gt;
  public enum PARTITION_STYLE : uint
  {
      /// &lt;summary&gt;
      /// Master boot record (MBR) format.
      /// &lt;/summary&gt;
      PARTITION_STYLE_MBR = 0,
  
      /// &lt;summary&gt;
      /// GUID Partition Table (GPT) format.
      /// &lt;/summary&gt;
      PARTITION_STYLE_GPT = 1,
  
      /// &lt;summary&gt;
      /// Partition not formatted in either of the recognized formats—MBR or GPT.
      /// &lt;/summary&gt;
      PARTITION_STYLE_RAW = 2
  }
  
  /// &lt;summary&gt;
  /// Contains partition information specific to master boot record (MBR) disks.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  public struct PARTITION_INFORMATION_MBR
  {
      #region Constants
      /// &lt;summary&gt;
      /// An unused entry partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_ENTRY_UNUSED = 0x00;
  
      /// &lt;summary&gt;
      /// A FAT12 file system partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_FAT_12 = 0x01;
  
      /// &lt;summary&gt;
      /// A FAT16 file system partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_FAT_16 = 0x04;
  
      /// &lt;summary&gt;
      /// An extended partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_EXTENDED = 0x05;
  
      /// &lt;summary&gt;
      /// An IFS partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_IFS = 0x07;
  
      /// &lt;summary&gt;
      /// A FAT32 file system partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_FAT32 = 0x0B;
  
      /// &lt;summary&gt;
      /// A logical disk manager (LDM) partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_LDM = 0x42;
  
      /// &lt;summary&gt;
      /// An NTFT partition.
      /// &lt;/summary&gt;
      public const byte PARTITION_NTFT = 0x80;
  
      /// &lt;summary&gt;
      /// A valid NTFT partition.
      /// 
      /// The high bit of a partition type code indicates that a partition is part of an NTFT mirror or striped array.
      /// &lt;/summary&gt;
      public const byte PARTITION_VALID_NTFT = 0xC0;
      #endregion
  
      /// &lt;summary&gt;
      /// The type of partition. For a list of values, see Disk Partition Types.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      [MarshalAs(UnmanagedType.U1)]
      public byte PartitionType;
  
      /// &lt;summary&gt;
      /// If this member is TRUE, the partition is bootable.
      /// &lt;/summary&gt;
      [FieldOffset(1)]
      [MarshalAs(UnmanagedType.I1)]
      public bool BootIndicator;
  
      /// &lt;summary&gt;
      /// If this member is TRUE, the partition is of a recognized type.
      /// &lt;/summary&gt;
      [FieldOffset(2)]
      [MarshalAs(UnmanagedType.I1)]
      public bool RecognizedPartition;
  
      /// &lt;summary&gt;
      /// The number of hidden sectors in the partition.
      /// &lt;/summary&gt;
      [FieldOffset(4)]
      public uint HiddenSectors;
  }
  
  /// &lt;summary&gt;
  /// Contains GUID partition table (GPT) partition information.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
  public struct PARTITION_INFORMATION_GPT
  {
      /// &lt;summary&gt;
      /// A GUID that identifies the partition type.
      /// 
      /// Each partition type that the EFI specification supports is identified by its own GUID, which is 
      /// published by the developer of the partition.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public Guid PartitionType;
  
      /// &lt;summary&gt;
      /// The GUID of the partition.
      /// &lt;/summary&gt;
      [FieldOffset(16)]
      public Guid PartitionId;
  
      /// &lt;summary&gt;
      /// The Extensible Firmware Interface (EFI) attributes of the partition.
      /// 
      /// &lt;/summary&gt;
      [FieldOffset(32)]
      public UInt64 Attributes;
  
      /// &lt;summary&gt;
      /// A wide-character string that describes the partition.
      /// &lt;/summary&gt;
      [FieldOffset(40)]
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
      public string Name;
  }
  /// &lt;summary&gt;
  /// Provides information about a drive's master boot record (MBR) partitions.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  private struct DRIVE_LAYOUT_INFORMATION_MBR
  {
      /// &lt;summary&gt;
      /// The signature of the drive.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public uint Signature;
  }
  
  /// &lt;summary&gt;
  /// Contains information about a drive's GUID partition table (GPT) partitions.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  private struct DRIVE_LAYOUT_INFORMATION_GPT
  {
      /// &lt;summary&gt;
      /// The GUID of the disk.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public Guid DiskId;
  
      /// &lt;summary&gt;
      /// The starting byte offset of the first usable block.
      /// &lt;/summary&gt;
      [FieldOffset(16)]
      public Int64 StartingUsableOffset;
  
      /// &lt;summary&gt;
      /// The size of the usable blocks on the disk, in bytes.
      /// &lt;/summary&gt;
      [FieldOffset(24)]
      public Int64 UsableLength;
  
      /// &lt;summary&gt;
      /// The maximum number of partitions that can be defined in the usable block.
      /// &lt;/summary&gt;
      [FieldOffset(32)]
      public uint MaxPartitionCount;
  }
  
  
  /// &lt;summary&gt;
  /// Contains information about a disk partition.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  public struct PARTITION_INFORMATION_EX
  {
      /// &lt;summary&gt;
      /// The format of the partition. For a list of values, see PARTITION_STYLE.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public PARTITION_STYLE PartitionStyle;
  
      /// &lt;summary&gt;
      /// The starting offset of the partition.
      /// &lt;/summary&gt;
      [FieldOffset(8)]
      public Int64 StartingOffset;
  
      /// &lt;summary&gt;
      /// The length of the partition, in bytes.
      /// &lt;/summary&gt;
      [FieldOffset(16)]
      public Int64 PartitionLength;
  
      /// &lt;summary&gt;
      /// The number of the partition (1-based).
      /// &lt;/summary&gt;
      [FieldOffset(24)]
      public uint PartitionNumber;
  
      /// &lt;summary&gt;
      /// If this member is TRUE, the partition information has changed. When you change a partition (with 
      /// IOCTL_DISK_SET_DRIVE_LAYOUT), the system uses this member to determine which partitions have changed
      /// and need their information rewritten.
      /// &lt;/summary&gt;
      [FieldOffset(28)]
      [MarshalAs(UnmanagedType.I1)]
      public bool RewritePartition;
  
      /// &lt;summary&gt;
      /// A PARTITION_INFORMATION_MBR structure that specifies partition information specific to master boot 
      /// record (MBR) disks. The MBR partition format is the standard AT-style format.
      /// &lt;/summary&gt;
      [FieldOffset(32)]
      public PARTITION_INFORMATION_MBR Mbr;
  
      /// &lt;summary&gt;
      /// A PARTITION_INFORMATION_GPT structure that specifies partition information specific to GUID partition 
      /// table (GPT) disks. The GPT format corresponds to the EFI partition format.
      /// &lt;/summary&gt;
      [FieldOffset(32)]
      public PARTITION_INFORMATION_GPT Gpt;
  }
  
  
  [StructLayout(LayoutKind.Explicit)]
  private struct DRIVE_LAYOUT_INFORMATION_UNION
  {
      [FieldOffset(0)]
      public DRIVE_LAYOUT_INFORMATION_MBR Mbr;
  
      [FieldOffset(0)]
      public DRIVE_LAYOUT_INFORMATION_GPT Gpt;
  }
  
  /// &lt;summary&gt;
  /// Contains extended information about a drive's partitions.
  /// &lt;/summary&gt;
  [StructLayout(LayoutKind.Explicit)]
  private struct DRIVE_LAYOUT_INFORMATION_EX
  {
      /// &lt;summary&gt;
      /// The style of the partitions on the drive enumerated by the PARTITION_STYLE enumeration.
      /// &lt;/summary&gt;
      [FieldOffset(0)]
      public PARTITION_STYLE PartitionStyle;
  
      /// &lt;summary&gt;
      /// The number of partitions on a drive.
      /// 
      /// On disks with the MBR layout, this value is always a multiple of 4. Any partitions that are unused have
      /// a partition type of PARTITION_ENTRY_UNUSED.
      /// &lt;/summary&gt;
      [FieldOffset(4)]
      public uint PartitionCount;
  
      /// &lt;summary&gt;
      /// A DRIVE_LAYOUT_INFORMATION_MBR structure containing information about the master boot record type 
      /// partitioning on the drive.
      /// &lt;/summary&gt;
      [FieldOffset(8)]
      public DRIVE_LAYOUT_INFORMATION_UNION Mbr;
  
      /// &lt;summary&gt;
      /// A DRIVE_LAYOUT_INFORMATION_GPT structure containing information about the GUID disk partition type 
      /// partitioning on the drive.
      /// &lt;/summary&gt;
      // [FieldOffset(8)]
      //public DRIVE_LAYOUT_INFORMATION_GPT Gpt;
  
      /// &lt;summary&gt;
      /// A variable-sized array of PARTITION_INFORMATION_EX structures, one structure for each partition on the 
      /// drive.
      /// &lt;/summary&gt;
      [FieldOffset(48)]
      [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
      public PARTITION_INFORMATION_EX[] PartitionEntry;
  
  }
  
  [StructLayout(LayoutKind.Explicit)]
  private struct CREATE_DISK_MBR
  {
      [FieldOffset(0)]
      public uint Signature;
  }
  
  [StructLayout(LayoutKind.Explicit)]
  private struct CREATE_DISK_GPT
  {
      [FieldOffset(0)]
      public Guid DiskId;
  
      [FieldOffset(16)]
      public uint MaxPartitionCount;
  }
  
  [StructLayout(LayoutKind.Explicit)]
  private struct CREATE_DISK
  {
      [FieldOffset(0)]
      public PARTITION_STYLE PartitionStyle;
  
      [FieldOffset(4)]
      public CREATE_DISK_MBR Mbr;
  
      [FieldOffset(4)]
      public CREATE_DISK_GPT Gpt;
  }
  
  
  static IntPtr GetHandle(int driveIndex, string physicalName)
  {
      IntPtr handle;
      //bool locked = false;
  
      Console.WriteLine(physicalName);
  
      handle = CreateFile(physicalName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                  IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
  
      if (handle == INVALID_HANDLE_VALUE)
      {
          Console.WriteLine(Marshal.GetLastWin32Error());
          return IntPtr.Zero;
      }
      return handle;
  }
  </code></pre>