public static string[] GetPhysicalMonitorNames(IntPtr hMonitor) { var mm = new MemPtr(); string[] sOut = null; PHYSICAL_MONITOR pm; uint nmon = 0; if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, out nmon)) { return(null); } int cb = Marshal.SizeOf <PHYSICAL_MONITOR>(); int size = cb * (int)nmon; mm.Alloc(size); try { if (GetPhysicalMonitorsFromHMONITOR(hMonitor, size, mm)) { sOut = new string[size]; int i; for (i = 0; i < nmon; i++) { pm = mm.ToStructAt <PHYSICAL_MONITOR>(i * cb); sOut[i] = pm.szPhysicalMonitorDescription; } DestroyPhysicalMonitors((uint)size, mm); } else { sOut = new string[] { NativeErrorMethods.FormatLastError() }; } mm.Free(); } catch { mm.Free(); } return(sOut); }
/// <summary> /// Retrieve the partition table of a GPT-layout disk, manually. /// Must be Administrator. /// </summary> /// <param name="inf">DiskDeviceInfo object to the physical disk to read.</param> /// <param name="gptInfo">Receives the drive layout information.</param> /// <returns>True if successful.</returns> /// <remarks></remarks> public static bool ReadRawGptDisk(string devicePath, ref RAW_GPT_DISK gptInfo) { // Demand Administrator for accessing a raw disk. AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); // Dim principalPerm As New PrincipalPermission(Nothing, "Administrators") // principalPerm.Demand() var hfile = IO.CreateFile(devicePath, IO.GENERIC_READ | IO.GENERIC_WRITE, IO.FILE_SHARE_READ | IO.FILE_SHARE_WRITE, IntPtr.Zero, IO.OPEN_EXISTING, IO.FILE_FLAG_NO_BUFFERING | IO.FILE_FLAG_RANDOM_ACCESS, IntPtr.Zero); if (hfile == DevProp.INVALID_HANDLE_VALUE) { return(false); } DISK_GEOMETRY_EX geo = default; // get the disk geometry to retrieve the sector (LBA) size. if (!DiskGeometry(hfile, ref geo)) { User32.CloseHandle(hfile); return(false); } // sector size (usually 512 bytes) uint bps = geo.Geometry.BytesPerSector; uint br = 0U; long lp = 0L; long lp2 = 0L; var mm = new MemPtr(bps * 2L); IO.SetFilePointerEx(hfile, 0L, ref lp, IO.FilePointerMoveMethod.Begin); IO.ReadFile(hfile, mm.Handle, bps * 2, ref br, IntPtr.Zero); var mbr = new RAW_MBR(); var gpt = new RAW_GPT_HEADER(); RAW_GPT_PARTITION[] gpp = null; // read the master boot record. mbr = mm.ToStructAt <RAW_MBR>(446L); // read the GPT structure header. gpt = mm.ToStructAt <RAW_GPT_HEADER>(bps); // check the partition header CRC. if (gpt.IsValid) { long lr = br; // seek to the LBA of the partition information. IO.SetFilePointerEx(hfile, (uint)(bps * gpt.PartitionEntryLBA), ref lr, IO.FilePointerMoveMethod.Begin); br = (uint)lr; // calculate the size of the partition table buffer. lp = gpt.NumberOfPartitions * gpt.PartitionEntryLength; // byte align to the sector size. if (lp % bps != 0L) { lp += bps - lp % bps; } // bump up the memory pointer. mm.ReAlloc(lp); mm.ZeroMemory(); // read the partition information into the pointer. IO.ReadFile(hfile, mm.Handle, (uint)lp, ref br, IntPtr.Zero); // check the partition table CRC. if (mm.CalculateCrc32() == gpt.PartitionArrayCRC32) { // disk is valid. lp = (uint)Marshal.SizeOf <RAW_GPT_PARTITION>(); br = 0U; int i; int c = (int)gpt.NumberOfPartitions; gpp = new RAW_GPT_PARTITION[c + 1]; // populate the drive information. for (i = 0; i < c; i++) { gpp[i] = mm.ToStructAt <RAW_GPT_PARTITION>(lp2); // break on empty GUID, we are past the last partition. if (gpp[i].PartitionTypeGuid == Guid.Empty) { break; } lp2 += lp; } // trim off excess records from the array. if (i < c) { if (i == 0) { gpp = Array.Empty <RAW_GPT_PARTITION>(); } else { Array.Resize(ref gpp, i); } } } } // free the resources. mm.Free(); User32.CloseHandle(hfile); // if gpp is nothing then some error occurred somewhere and we did not succeed. if (gpp is null) { return(false); } // create a new RAW_GPT_DISK structure. gptInfo = new RAW_GPT_DISK(); gptInfo.Header = gpt; gptInfo.Partitions = gpp; // we have succeeded. return(true); }