/// <summary> /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365194(v=vs.85).aspx" /> /// </summary> public VOLUME_DISK_EXTENTS VolumeGetVolumeDiskExtents() { // Fetch in increments of 32 bytes, as one extent (the most common case) is one extent pr. volume. byte[] data = DeviceIoControlHelper.InvokeIoControlUnknownSize(Handle, IOControlCode.VolumeGetVolumeDiskExtents, 32); // Build the VOLUME_DISK_EXTENTS structure VOLUME_DISK_EXTENTS res = new VOLUME_DISK_EXTENTS(); res.NumberOfDiskExtents = BitConverter.ToUInt32(data, 0); res.Extents = new DISK_EXTENT[res.NumberOfDiskExtents]; using (UnmanagedMemory dataPtr = new UnmanagedMemory(data)) { // TODO: This code needs to be tested for volumes with more than one extent. for (int i = 0; i < res.NumberOfDiskExtents; i++) { IntPtr currentDataPtr = new IntPtr(dataPtr.Handle.ToInt64() + 8 + i * MarshalHelper.SizeOf <DISK_EXTENT>()); DISK_EXTENT extent = currentDataPtr.ToStructure <DISK_EXTENT>(); res.Extents[i] = extent; } } return(res); }
public DISK_EXTENT[] ToStructure() { bool success = false; DangerousAddRef(ref success); if (!success) { throw new InvalidOperationException(); } try { int length = Marshal.ReadInt32(handle); DISK_EXTENT[] extents = new DISK_EXTENT[length]; int arrayElem = Marshal.SizeOf(typeof(DISK_EXTENT)); IntPtr arrayStart = handle + 8; for (int i = 0; i < length; i++) { extents[i] = (DISK_EXTENT)Marshal.PtrToStructure(arrayStart, typeof(DISK_EXTENT)); arrayStart += arrayElem; } return(extents); } finally { DangerousRelease(); } }
/// <summary> /// Get volume disk extents for volumes that may or may not span more than one physical drive. /// </summary> /// <param name="devicePath">The device path of the volume.</param> /// <returns>An array of DiskExtent structures.</returns> /// <remarks></remarks> public static DiskExtent[] GetDiskExtentsFor(string devicePath) { DiskExtent[] deOut = null; MemPtr inBuff = new MemPtr(); int inSize; IntPtr file; int h = 0; var de = new DISK_EXTENT(); var ve = new VOLUME_DISK_EXTENTS(); bool r; file = IO.CreateFile(devicePath, IO.GENERIC_READ, IO.FILE_SHARE_READ | IO.FILE_SHARE_WRITE, IntPtr.Zero, IO.OPEN_EXISTING, IO.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); if (file == DevProp.INVALID_HANDLE_VALUE) { return(null); } uint arb = 0; inSize = Marshal.SizeOf(de) + Marshal.SizeOf(ve); inBuff.Length = inSize; r = DeviceIoControl(file, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, inBuff, (uint)inSize, ref arb, IntPtr.Zero); if (!r && User32.GetLastError() == ERROR_MORE_DATA) { inBuff.Length = inSize * inBuff.IntAt(0L); r = DeviceIoControl(file, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, inBuff, (uint)inSize, ref arb, IntPtr.Zero); } if (!r) { inBuff.Free(); User32.CloseHandle(file); return(null); } User32.CloseHandle(file); ve = VOLUME_DISK_EXTENTS.FromPtr(inBuff); inBuff.Free(); h = 0; deOut = new DiskExtent[ve.Extents.Length]; foreach (var currentDe in ve.Extents) { de = currentDe; deOut[h].PhysicalDevice = de.DiskNumber; deOut[h].Space = de.Space; deOut[h].Size = de.ExtentLength; deOut[h].Offset = de.StartingOffset; h += 1; } return(deOut); }
public Extents(string name) { // Remove trailing '/' character from path string newname = name.Substring(0, name.Length - 1); IntPtr volhandle = CreateFile(newname, EFileAccess.Any, EFileShare.Read | EFileShare.Write, IntPtr.Zero, ECreationDisposition.OpenExisting, EFileAttributes.Normal, 0); if (volhandle.ToInt32() == INVALID_HANDLE_VALUE) { return; } try { VOLUME_DISK_EXTENTS vextents = new VOLUME_DISK_EXTENTS(); DISK_EXTENT dextent = new DISK_EXTENT(); uint numextents = 1; int allocsize = (int)Marshal.SizeOf(vextents) + (int)numextents * (int)Marshal.SizeOf(dextent); IntPtr memblock = IntPtr.Zero; IntPtr alloced; memblock = Marshal.AllocHGlobal((int)allocsize); alloced = memblock; try { int returned = 0; VOLUME_DISK_EXTENTS diskExtents = new VOLUME_DISK_EXTENTS(); while (true) { if (!DeviceIoControl(volhandle, IoctlControlCodes.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, memblock, allocsize, out returned, 0)) { int err = Marshal.GetLastWin32Error(); if ((err == ERROR_INSUFFICIENT_BUFFER) || (err == ERROR_MORE_DATA)) { Marshal.PtrToStructure(memblock, diskExtents); numextents = diskExtents.NumberOfDiskExtents; allocsize = (int)Marshal.SizeOf(vextents) + (int)numextents * (int)Marshal.SizeOf(dextent); memblock = Marshal.ReAllocHGlobal(memblock, new IntPtr(allocsize)); alloced = memblock; continue; } else { return; } } break; } Marshal.PtrToStructure(memblock, diskExtents); memblock = new IntPtr(memblock.ToInt64() + Marshal.SizeOf(diskExtents)); for (int i = 0; i < diskExtents.NumberOfDiskExtents; i++) { Marshal.PtrToStructure(memblock, dextent); Extent extent = new Extent { DiskNumber = dextent.DiskNumber, ExtentLength = dextent.ExtentLength, StartingOffset = dextent.StartingOffset }; this.Add(extent); memblock = new IntPtr(memblock.ToInt64() + Marshal.SizeOf(dextent)); } } finally { Marshal.FreeHGlobal(alloced); } } catch (Exception e) { WmiBase.Singleton.DebugMsg("Extent listing exception : " + e.ToString()); throw; } finally { CloseHandle(volhandle); } }