2012-04-25 61 views
3

对于一个项目,我想在NTFS分区上的所有免费/使用群集的列表。 为此,我不得不转储$位图文件,并解析其内容。

很少有API和网络上的例子,但不过他们似乎并不管用。有没有一个简单的方法/代码示例只是复制$位图文件的地方。

是使用FSCTL_GET_VOLUME_BITMAP的唯一途径?理想情况下,我想用C#来完成它。

+1

在这里,我想'FSCTL_GET_VOLUME_BITMAP' * *是最简单的方式... – Gabe 2012-04-25 06:18:26

+1

我希望你明白,除非文件系统是完全闲置,您检索位图中的第二个,这是过时的。 .. – MJZ 2012-11-14 21:53:28

+0

@MJZ但读取文件将使分区_not_空闲。分区必须卸载。 – 2013-06-21 12:52:03

回答

1

你一定要去简单的方法,使用IOCTL,而不是试图直接读取$Bitmap。当然,如果有人为你做了,你不必自己去做。事实证明,一个MSDN博客已经写了一个可爱的小包装给你:

http://blogs.msdn.com/b/jeffrey_wall/archive/2004/09/13/229137.aspx

全班同学正在代码超过300行,所以我不会发布这一切,但这里的功能获取卷位图:

/// <summary> 
    /// Get cluster usage for a device 
    /// </summary> 
    /// <param name="DeviceName">use "c:"</param> 
    /// <returns>a bitarray for each cluster</returns> 
    static public BitArray GetVolumeMap(string DeviceName) 
    { 
     IntPtr pAlloc = IntPtr.Zero; 
     IntPtr hDevice = IntPtr.Zero; 

     try 
     { 
      hDevice = OpenVolume(DeviceName); 

      Int64 i64 = 0; 

      GCHandle handle = GCHandle.Alloc(i64, GCHandleType.Pinned); 
      IntPtr p = handle.AddrOfPinnedObject(); 

      // alloc off more than enough for my machine 
      // 64 megs == 67108864 bytes == 536870912 bits == cluster count 
      // NTFS 4k clusters == 2147483648 k of storage == 2097152 megs == 2048 gig disk storage 
      uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1 meg * 64 == 64 megs 

      uint size = 0; 
      pAlloc = Marshal.AllocHGlobal((int)q); 
      IntPtr pDest = pAlloc; 

      bool fResult = DeviceIoControl(
       hDevice, 
       FSConstants.FSCTL_GET_VOLUME_BITMAP, 
       p, 
       (uint)Marshal.SizeOf(i64), 
       pDest, 
       q, 
       ref size, 
       IntPtr.Zero); 

      if (!fResult) 
      { 
       throw new Exception(Marshal.GetLastWin32Error().ToString()); 
      } 
      handle.Free(); 

      /* 
      object returned was... 
     typedef struct 
     { 
     LARGE_INTEGER StartingLcn; 
     LARGE_INTEGER BitmapSize; 
     BYTE Buffer[1]; 
     } VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER; 
      */ 
      Int64 StartingLcn = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); 

      Debug.Assert(StartingLcn == 0); 

      pDest = (IntPtr)((Int64)pDest + 8); 
      Int64 BitmapSize = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); 

      Int32 byteSize = (int)(BitmapSize/8); 
      byteSize++; // round up - even with no remainder 

      IntPtr BitmapBegin = (IntPtr)((Int64)pDest + 8); 

      byte[] byteArr = new byte[byteSize]; 

      Marshal.Copy(BitmapBegin, byteArr, 0, (Int32)byteSize); 

      BitArray retVal = new BitArray(byteArr); 
      retVal.Length = (int)BitmapSize; // truncate to exact cluster count 
      return retVal; 
     } 
     finally 
     { 
      CloseHandle(hDevice); 
      hDevice = IntPtr.Zero; 

      Marshal.FreeHGlobal(pAlloc); 
      pAlloc = IntPtr.Zero; 
     } 
    } 
+0

你可以在这里添加一些代码吗? – 2013-05-23 04:30:37

+0

@Cole:Code做什么? – Gabe 2013-05-23 05:31:14

+0

@Gabe代码的链接,所以它不是一个临界“链接只回答”。但看到代码块有多大,没关系。 – 2013-05-23 06:45:06

1

NFI.EXE这是(曾经是)的“OEM支持工具”的一部分可以枚举所有NTFS分区项目。它也可能能够转储$ Bitmap的内容。

enter image description here