public void DrawBlocks() { if (!Volume.BitmapLoaded) { return; } //if (Drawing.IsDrawing) // return; // Wait until width is not NaN while (double.IsNaN(GetWidth())) { } ThreadSafeWidth = GetWidth(); int currentX = 0; int currentY = 0; uint BytesReturned = 0; uint BitmapSize = (65536 + 2 * sizeof(ulong)); int err; ulong currLcn = 0; ulong?lastLcn = 0; ulong lastCluster = 0; ulong?cluster = null; ulong?cluster2 = null; ulong clusterCount = 0; ulong clusterCount2 = 0; ulong numFree = 0; ulong numFree2 = 0; ulong numFree3 = 0; int[] BitShift = { 1, 2, 4, 8, 16, 32, 64, 128 }; ulong Max = Utils.Min(Volume.PartInfo.ClusterCount, 8 * 65536); do { if (_cancellationTokenSource.IsCancellationRequested) { break; } GCHandle handle = GCHandle.Alloc(currLcn, GCHandleType.Pinned); var CurrentLCNPtr = handle.AddrOfPinnedObject(); var pDest = Marshal.AllocHGlobal((int)BitmapSize); PInvoke.DeviceIoControl( Volume.Handle, PInvoke.FSConstants.FSCTL_GET_VOLUME_BITMAP, CurrentLCNPtr, (uint)Marshal.SizeOf(currLcn), pDest, BitmapSize, ref BytesReturned, IntPtr.Zero); err = Marshal.GetLastWin32Error(); if (err != PInvoke.ERROR_MORE_DATA && err != PInvoke.ERROR_HANDLE_EOF) { break; } PInvoke.VOLUME_BITMAP_BUFFER BitmapBuffer = new PInvoke.VOLUME_BITMAP_BUFFER(pDest, (int)BitmapSize); ulong i; for (i = 0; i < Max; i++) { if (_cancellationTokenSource.IsCancellationRequested) { break; } if ((BitmapBuffer.Buffer[i / 8] & BitShift[i % 8]) > 0) { // Cluster is used if (cluster.HasValue) { if ((lastLcn.HasValue) && cluster.Value == lastLcn.Value) { lastLcn = null; } else { numFree2 += numFree; //cFreeSpaceGaps++; if (BlockSize == 1) { DrawBlocks(cluster2.Value, cluster2.Value + numFree2, 0xFFFFFF); } lastCluster = cluster2.Value + numFree2; lastLcn = cluster; numFree = 0; numFree2 = 0; clusterCount2 = 0; cluster = null; cluster2 = null; } } } else { // Cluster is free if (!cluster.HasValue) { cluster = currLcn + i; if (BlockSize == 1) { DrawBlocks(lastCluster, cluster.Value, ColFile); } cluster2 = cluster; numFree = 1; numFree3++; } else { numFree++; numFree3++; } } clusterCount++; if (clusterCount == clustersPerBlock) { clusterCount2 += clustersPerBlock; } // prevent drawing as one big block if (clusterCount2 >= clustersPerLine && BlockSize == 1) { if (cluster2.HasValue && numFree > clustersPerLine) { DrawBlocks(cluster2.Value, cluster2.Value + numFree, ColWhite); } else if (numFree == 0) { DrawBlocks(currLcn + i - clustersPerLine, currLcn + i, ColFile); } clusterCount2 = 0; } // draw the shit if (clusterCount >= clustersPerBlock) { if (BlockSize != 1) { DrawNoBlockBound(currentX, currentY); // just make sure all is new if (numFree3 >= clustersPerBlock) { DrawBlockAt(currentX, currentY, ColWhite); } else if (numFree3 == 0) { DrawBlockAt(currentX, currentY, ColFile); } else if (numFree3 >= (clustersPerBlock / colorSteps) * 4) { DrawBlockAt(currentX, currentY, ColF5); } else if (numFree3 >= (clustersPerBlock / colorSteps) * 3) { DrawBlockAt(currentX, currentY, ColF4); } else if (numFree3 >= (clustersPerBlock / colorSteps) * 2) { DrawBlockAt(currentX, currentY, ColF3); } else if (numFree3 >= (clustersPerBlock / colorSteps)) { DrawBlockAt(currentX, currentY, ColF2); } else { DrawBlockAt(currentX, currentY, ColF1); } /* * else * for (j=colorsteps-1; j>0; j--) * if (numFree3 >= (int)(clustersPB/colorsteps)*j || j==1) { * DrawBlockAt(x, y, LighterVal(ColFile, 256/(colorsteps-j+1)-(colorsteps-j) )); * break; * } */ currentX += BlockSize; if (currentX > (int)(ThreadSafeWidth - BlockSize)) { // move to next y-line currentX = 0; currentY += BlockSize; } numFree3 = 0; } clusterCount = 0; } } // for all clusters in this pair // Move to the next block currLcn = BitmapBuffer.StartingLcn.QuadPart + i; } while ((err == PInvoke.ERROR_MORE_DATA) && (currLcn < Volume.PartInfo.ClusterCount)); if (clusterCount > 0) { //cFreeSpaceGaps++; // draw last cluster if (BlockSize > 1) { DrawNoBlockBound(currentX, currentY); if (numFree3 == clusterCount) { DrawBlockAt(currentX, currentY, ColWhite); } else { if (numFree3 > 0) { uint col = Utils.LighterVal(ColFile, (int)(((float)((int)(clustersPerBlock - (clustersPerBlock - numFree3))) / (int)clustersPerBlock) * 255.0)); DrawBlockAt(currentX, currentY, col); } else { DrawBlockAt(currentX, currentY, ColFile); } } } else { if (cluster2.HasValue) { if (numFree > 0) { DrawBlocks(cluster2.Value, cluster2.Value + numFree, ColWhite); } else { DrawBlocks(lastCluster, currLcn, ColFile); } } } } // Update window if (Dispatcher.Thread != Thread.CurrentThread) { Dispatcher.Invoke(() => draw.InvalidateVisual()); } else { draw.InvalidateVisual(); } }
/// <summary> /// Gets drive bitmap /// </summary> /// <returns></returns> public bool GetBitmap() { Int64 StartingLCN = 0; uint BytesReturned = 0; GCHandle handle = GCHandle.Alloc(StartingLCN, GCHandleType.Pinned); var StartingLCNPtr = handle.AddrOfPinnedObject(); //BitmapSize = (uint)Marshal.SizeOf(typeof(PInvoke.VOLUME_BITMAP_BUFFER)) + 4; uint BitmapSize = 28; var pDest = Marshal.AllocHGlobal((int)BitmapSize); var Result = PInvoke.DeviceIoControl( Handle, PInvoke.FSConstants.FSCTL_GET_VOLUME_BITMAP, StartingLCNPtr, (uint)Marshal.SizeOf(StartingLCN), pDest, BitmapSize, ref BytesReturned, IntPtr.Zero); // Bad result? if (Result == false && Marshal.GetLastWin32Error() != PInvoke.ERROR_MORE_DATA) { Marshal.FreeHGlobal(pDest); return(false); } var Bitmap = new PInvoke.VOLUME_BITMAP_BUFFER(pDest, false); BitmapSize = (uint)Marshal.SizeOf(typeof(PInvoke.VOLUME_BITMAP_BUFFER)) + ((uint)Bitmap.BitmapSize.QuadPart / 8) + 1; pDest = Marshal.ReAllocHGlobal(pDest, (IntPtr)BitmapSize); Result = PInvoke.DeviceIoControl( Handle, PInvoke.FSConstants.FSCTL_GET_VOLUME_BITMAP, StartingLCNPtr, (uint)Marshal.SizeOf(StartingLCN), pDest, BitmapSize, ref BytesReturned, IntPtr.Zero); if (Result == false) { Debug.WriteLine("Couldn't properly read volume bitmap"); Marshal.FreeHGlobal(pDest); return(false); } Bitmap = new PInvoke.VOLUME_BITMAP_BUFFER(pDest, true); /* * BitmapSize = (uint)Marshal.SizeOf(typeof(PInvoke.VOLUME_BITMAP_BUFFER)) + ((uint)Bitmap.BitmapSize.QuadPart / 8) + 1; */ PartInfo.ClusterCount = Bitmap.BitmapSize.QuadPart; BitmapDetail = Bitmap.Buffer; Marshal.FreeHGlobal(pDest); return(true); }