2012-04-25 62 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