I have some C# code that is supposed to wrap the defrag APIs and I am trying
to convert it to VB.Net (2003). But, I keep having problems.
The C# code is relatively short, so I'll post it here.....
--------
//
// a set of simple C# wrappers over the NT Defragmenter APIs
//
//
// Refrences
//
// http://www.sysinternals.com/ntw2k/info/defrag.shtml
//
// msdn how-to
// ms-help://MS.MSDNQTR.2004 JUL.1033/fileio/base/defragmenting_f iles.htm
//
//
// FSCTL_GET_VOLUM E_BITMAP
//
//
// interesting structures...
// FSCTL_MOVE_FILE
// FSCTL_GET_RETRI EVAL_POINTERS
// RETRIEVAL_POINT ERS_BUFFER
// FSCTL_GET_RETRI EVAL_POINTERS
//
// DeviceIoControl
//
//
using System;
using System.Diagnost ics;
using System.Collecti ons;
using System.Runtime. InteropServices ;
namespace defraglib
{
public class IOWrapper
{
//
// CreateFile constants
//
const uint FILE_SHARE_READ = 0x00000001;
const uint FILE_SHARE_WRIT E = 0x00000002;
const uint FILE_SHARE_DELE TE = 0x00000004;
const uint OPEN_EXISTING = 3;
const uint GENERIC_READ = (0x80000000);
const uint GENERIC_WRITE = (0x40000000);
const uint FILE_FLAG_NO_BU FFERING = 0x20000000;
const uint FILE_READ_ATTRI BUTES = (0x0080);
const uint FILE_WRITE_ATTR IBUTES = 0x0100;
const uint ERROR_INSUFFICI ENT_BUFFER = 122;
[DllImport("kern el32.dll", SetLastError = true)]
static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess ,
uint dwShareMode,
IntPtr lpSecurityAttri butes,
uint dwCreationDispo sition,
uint dwFlagsAndAttri butes,
IntPtr hTemplateFile);
[DllImport("kern el32.dll", SetLastError = true)]
static extern int CloseHandle(Int Ptr hObject);
[DllImport("kern el32.dll", SetLastError = true)]
static extern bool DeviceIoControl (
IntPtr hDevice,
uint dwIoControlCode ,
IntPtr lpInBuffer,
uint nInBufferSize,
[Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned ,
IntPtr lpOverlapped);
static private IntPtr OpenVolume(stri ng DeviceName)
{
IntPtr hDevice;
hDevice = CreateFile(
@"\\.\" + DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRIT E,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if ((int)hDevice == -1)
{
throw new Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
return hDevice;
}
static private IntPtr OpenFile(string path)
{
IntPtr hFile;
hFile = CreateFile(
path,
FILE_READ_ATTRI BUTES | FILE_WRITE_ATTR IBUTES,
FILE_SHARE_READ | FILE_SHARE_WRIT E,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if ((int)hFile == -1)
{
throw new Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
return hFile;
}
/// <summary>
/// Get cluster usage for a device
/// </summary>
/// <param name="DeviceNam e">use "c:"</param>
/// <returns>a bitarray for each cluster</returns>
static public BitArray GetVolumeMap(st ring DeviceName)
{
IntPtr pAlloc = IntPtr.Zero;
IntPtr hDevice = IntPtr.Zero;
try
{
hDevice = OpenVolume(Devi ceName);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc( i64, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
// 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.AllocHG lobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl (
hDevice,
FSConstants.FSC TL_GET_VOLUME_B ITMAP,
p,
(uint)Marshal.S izeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
handle.Free();
/*
object returned was...
typedef struct
{
LARGE_INTEGER StartingLcn;
LARGE_INTEGER BitmapSize;
BYTE Buffer[1];
} VOLUME_BITMAP_B UFFER, *PVOLUME_BITMAP _BUFFER;
*/
Int64 StartingLcn = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Debug.Assert(St artingLcn == 0);
pDest = (IntPtr)((Int64 )pDest + 8);
Int64 BitmapSize = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Int32 byteSize = (int)(BitmapSiz e / 8);
byteSize++; // round up - even with no remainder
IntPtr BitmapBegin = (IntPtr)((Int64 )pDest + 8);
byte[] byteArr = new byte[byteSize];
Marshal.Copy(Bi tmapBegin, byteArr, 0, (Int32)byteSize );
BitArray retVal = new BitArray(byteAr r);
retVal.Length = (int)BitmapSize ; // truncate to exact
cluster count
return retVal;
}
finally
{
CloseHandle(hDe vice);
hDevice = IntPtr.Zero;
Marshal.FreeHGl obal(pAlloc);
pAlloc = IntPtr.Zero;
}
}
/// <summary>
/// returns a 2*number of extents array -
/// the vcn and the lcn as pairs
/// </summary>
/// <param name="path">fil e to get the map for ex:
"c:\windows\exp lorer.exe" </param>
/// <returns>An array of [virtual cluster, physical
cluster]</returns>
static public Array GetFileMap(stri ng path)
{
IntPtr hFile = IntPtr.Zero;
IntPtr pAlloc = IntPtr.Zero;
try
{
hFile = OpenFile(path);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc( i64, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1
meg * 64 == 64 megs
uint size = 0;
pAlloc = Marshal.AllocHG lobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl (
hFile,
FSConstants.FSC TL_GET_RETRIEVA L_POINTERS,
p,
(uint)Marshal.S izeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
handle.Free();
/*
returned back one of...
typedef struct RETRIEVAL_POINT ERS_BUFFER {
DWORD ExtentCount;
LARGE_INTEGER StartingVcn;
struct {
LARGE_INTEGER NextVcn;
LARGE_INTEGER Lcn;
} Extents[1];
} RETRIEVAL_POINT ERS_BUFFER, *PRETRIEVAL_POI NTERS_BUFFER;
*/
Int32 ExtentCount = (Int32)Marshal. PtrToStructure( pDest,
typeof(Int32));
pDest = (IntPtr)((Int64 )pDest + 4);
Int64 StartingVcn = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Debug.Assert(St artingVcn == 0);
pDest = (IntPtr)((Int64 )pDest + 8);
// now pDest points at an array of pairs of Int64s.
Array retVal = Array.CreateIns tance(typeof(In t64), new
int[2] { ExtentCount, 2 });
for (int i = 0; i < ExtentCount; i++)
{
for (int j = 0; j < 2; j++)
{
Int64 v = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
retVal.SetValue (v, new int[2] { i, j });
pDest = (IntPtr)((Int64 )pDest + 8);
}
}
return retVal;
}
finally
{
CloseHandle(hFi le);
hFile = IntPtr.Zero;
Marshal.FreeHGl obal(pAlloc);
pAlloc = IntPtr.Zero;
}
}
/// <summary>
/// input structure for use in MoveFile
/// </summary>
private struct MoveFileData
{
public IntPtr hFile;
public Int64 StartingVCN;
public Int64 StartingLCN;
public Int32 ClusterCount;
}
/// <summary>
/// move a virtual cluster for a file to a logical cluster on disk,
repeat for count clusters
/// </summary>
/// <param name="deviceNam e">device to move on"c:"</param>
/// <param name="path">fil e to muck with
"c:\windows\exp lorer.exe"</param>
/// <param name="VCN">clus ter number in file to move</param>
/// <param name="LCN">clus ter on disk to move to</param>
/// <param name="count">fo r how many clusters</param>
static public void MoveFile(string deviceName, string path, Int64
VCN, Int64 LCN, Int32 count)
{
IntPtr hVol = IntPtr.Zero;
IntPtr hFile = IntPtr.Zero;
try
{
hVol = OpenVolume(devi ceName);
hFile = OpenFile(path);
MoveFileData mfd = new MoveFileData();
mfd.hFile = hFile;
mfd.StartingVCN = VCN;
mfd.StartingLCN = LCN;
mfd.ClusterCoun t = count;
GCHandle handle = GCHandle.Alloc( mfd, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
uint bufSize = (uint)Marshal.S izeOf(mfd);
uint size = 0;
bool fResult = DeviceIoControl (
hVol,
FSConstants.FSC TL_MOVE_FILE,
p,
bufSize,
IntPtr.Zero, // no output data from this FSCTL
0,
ref size,
IntPtr.Zero);
handle.Free();
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
}
finally
{
CloseHandle(hVo l);
CloseHandle(hFi le);
}
}
}
/// <summary>
/// constants lifted from winioctl.h from platform sdk
/// </summary>
internal class FSConstants
{
const uint FILE_DEVICE_FIL E_SYSTEM = 0x00000009;
const uint METHOD_NEITHER = 3;
const uint METHOD_BUFFERED = 0;
const uint FILE_ANY_ACCESS = 0;
const uint FILE_SPECIAL_AC CESS = FILE_ANY_ACCESS ;
public static uint FSCTL_GET_VOLUM E_BITMAP =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 27, METHOD_NEITHER, FILE_ANY_ACCESS );
public static uint FSCTL_GET_RETRI EVAL_POINTERS =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 28, METHOD_NEITHER, FILE_ANY_ACCESS );
public static uint FSCTL_MOVE_FILE =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 29, METHOD_BUFFERED , FILE_SPECIAL_AC CESS);
static uint CTL_CODE(uint DeviceType, uint Function, uint Method,
uint Access)
{
return ((DeviceType) << 16) | ((Access) << 14) | ((Function) <<
2) | (Method);
}
}
}
-----
I'd be very grateful for any help with this conversion that you could offer.
Thanks!
to convert it to VB.Net (2003). But, I keep having problems.
The C# code is relatively short, so I'll post it here.....
--------
//
// a set of simple C# wrappers over the NT Defragmenter APIs
//
//
// Refrences
//
// http://www.sysinternals.com/ntw2k/info/defrag.shtml
//
// msdn how-to
// ms-help://MS.MSDNQTR.2004 JUL.1033/fileio/base/defragmenting_f iles.htm
//
//
// FSCTL_GET_VOLUM E_BITMAP
//
//
// interesting structures...
// FSCTL_MOVE_FILE
// FSCTL_GET_RETRI EVAL_POINTERS
// RETRIEVAL_POINT ERS_BUFFER
// FSCTL_GET_RETRI EVAL_POINTERS
//
// DeviceIoControl
//
//
using System;
using System.Diagnost ics;
using System.Collecti ons;
using System.Runtime. InteropServices ;
namespace defraglib
{
public class IOWrapper
{
//
// CreateFile constants
//
const uint FILE_SHARE_READ = 0x00000001;
const uint FILE_SHARE_WRIT E = 0x00000002;
const uint FILE_SHARE_DELE TE = 0x00000004;
const uint OPEN_EXISTING = 3;
const uint GENERIC_READ = (0x80000000);
const uint GENERIC_WRITE = (0x40000000);
const uint FILE_FLAG_NO_BU FFERING = 0x20000000;
const uint FILE_READ_ATTRI BUTES = (0x0080);
const uint FILE_WRITE_ATTR IBUTES = 0x0100;
const uint ERROR_INSUFFICI ENT_BUFFER = 122;
[DllImport("kern el32.dll", SetLastError = true)]
static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess ,
uint dwShareMode,
IntPtr lpSecurityAttri butes,
uint dwCreationDispo sition,
uint dwFlagsAndAttri butes,
IntPtr hTemplateFile);
[DllImport("kern el32.dll", SetLastError = true)]
static extern int CloseHandle(Int Ptr hObject);
[DllImport("kern el32.dll", SetLastError = true)]
static extern bool DeviceIoControl (
IntPtr hDevice,
uint dwIoControlCode ,
IntPtr lpInBuffer,
uint nInBufferSize,
[Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned ,
IntPtr lpOverlapped);
static private IntPtr OpenVolume(stri ng DeviceName)
{
IntPtr hDevice;
hDevice = CreateFile(
@"\\.\" + DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRIT E,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if ((int)hDevice == -1)
{
throw new Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
return hDevice;
}
static private IntPtr OpenFile(string path)
{
IntPtr hFile;
hFile = CreateFile(
path,
FILE_READ_ATTRI BUTES | FILE_WRITE_ATTR IBUTES,
FILE_SHARE_READ | FILE_SHARE_WRIT E,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if ((int)hFile == -1)
{
throw new Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
return hFile;
}
/// <summary>
/// Get cluster usage for a device
/// </summary>
/// <param name="DeviceNam e">use "c:"</param>
/// <returns>a bitarray for each cluster</returns>
static public BitArray GetVolumeMap(st ring DeviceName)
{
IntPtr pAlloc = IntPtr.Zero;
IntPtr hDevice = IntPtr.Zero;
try
{
hDevice = OpenVolume(Devi ceName);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc( i64, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
// 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.AllocHG lobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl (
hDevice,
FSConstants.FSC TL_GET_VOLUME_B ITMAP,
p,
(uint)Marshal.S izeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
handle.Free();
/*
object returned was...
typedef struct
{
LARGE_INTEGER StartingLcn;
LARGE_INTEGER BitmapSize;
BYTE Buffer[1];
} VOLUME_BITMAP_B UFFER, *PVOLUME_BITMAP _BUFFER;
*/
Int64 StartingLcn = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Debug.Assert(St artingLcn == 0);
pDest = (IntPtr)((Int64 )pDest + 8);
Int64 BitmapSize = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Int32 byteSize = (int)(BitmapSiz e / 8);
byteSize++; // round up - even with no remainder
IntPtr BitmapBegin = (IntPtr)((Int64 )pDest + 8);
byte[] byteArr = new byte[byteSize];
Marshal.Copy(Bi tmapBegin, byteArr, 0, (Int32)byteSize );
BitArray retVal = new BitArray(byteAr r);
retVal.Length = (int)BitmapSize ; // truncate to exact
cluster count
return retVal;
}
finally
{
CloseHandle(hDe vice);
hDevice = IntPtr.Zero;
Marshal.FreeHGl obal(pAlloc);
pAlloc = IntPtr.Zero;
}
}
/// <summary>
/// returns a 2*number of extents array -
/// the vcn and the lcn as pairs
/// </summary>
/// <param name="path">fil e to get the map for ex:
"c:\windows\exp lorer.exe" </param>
/// <returns>An array of [virtual cluster, physical
cluster]</returns>
static public Array GetFileMap(stri ng path)
{
IntPtr hFile = IntPtr.Zero;
IntPtr pAlloc = IntPtr.Zero;
try
{
hFile = OpenFile(path);
Int64 i64 = 0;
GCHandle handle = GCHandle.Alloc( i64, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1
meg * 64 == 64 megs
uint size = 0;
pAlloc = Marshal.AllocHG lobal((int)q);
IntPtr pDest = pAlloc;
bool fResult = DeviceIoControl (
hFile,
FSConstants.FSC TL_GET_RETRIEVA L_POINTERS,
p,
(uint)Marshal.S izeOf(i64),
pDest,
q,
ref size,
IntPtr.Zero);
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
handle.Free();
/*
returned back one of...
typedef struct RETRIEVAL_POINT ERS_BUFFER {
DWORD ExtentCount;
LARGE_INTEGER StartingVcn;
struct {
LARGE_INTEGER NextVcn;
LARGE_INTEGER Lcn;
} Extents[1];
} RETRIEVAL_POINT ERS_BUFFER, *PRETRIEVAL_POI NTERS_BUFFER;
*/
Int32 ExtentCount = (Int32)Marshal. PtrToStructure( pDest,
typeof(Int32));
pDest = (IntPtr)((Int64 )pDest + 4);
Int64 StartingVcn = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
Debug.Assert(St artingVcn == 0);
pDest = (IntPtr)((Int64 )pDest + 8);
// now pDest points at an array of pairs of Int64s.
Array retVal = Array.CreateIns tance(typeof(In t64), new
int[2] { ExtentCount, 2 });
for (int i = 0; i < ExtentCount; i++)
{
for (int j = 0; j < 2; j++)
{
Int64 v = (Int64)Marshal. PtrToStructure( pDest,
typeof(Int64));
retVal.SetValue (v, new int[2] { i, j });
pDest = (IntPtr)((Int64 )pDest + 8);
}
}
return retVal;
}
finally
{
CloseHandle(hFi le);
hFile = IntPtr.Zero;
Marshal.FreeHGl obal(pAlloc);
pAlloc = IntPtr.Zero;
}
}
/// <summary>
/// input structure for use in MoveFile
/// </summary>
private struct MoveFileData
{
public IntPtr hFile;
public Int64 StartingVCN;
public Int64 StartingLCN;
public Int32 ClusterCount;
}
/// <summary>
/// move a virtual cluster for a file to a logical cluster on disk,
repeat for count clusters
/// </summary>
/// <param name="deviceNam e">device to move on"c:"</param>
/// <param name="path">fil e to muck with
"c:\windows\exp lorer.exe"</param>
/// <param name="VCN">clus ter number in file to move</param>
/// <param name="LCN">clus ter on disk to move to</param>
/// <param name="count">fo r how many clusters</param>
static public void MoveFile(string deviceName, string path, Int64
VCN, Int64 LCN, Int32 count)
{
IntPtr hVol = IntPtr.Zero;
IntPtr hFile = IntPtr.Zero;
try
{
hVol = OpenVolume(devi ceName);
hFile = OpenFile(path);
MoveFileData mfd = new MoveFileData();
mfd.hFile = hFile;
mfd.StartingVCN = VCN;
mfd.StartingLCN = LCN;
mfd.ClusterCoun t = count;
GCHandle handle = GCHandle.Alloc( mfd, GCHandleType.Pi nned);
IntPtr p = handle.AddrOfPi nnedObject();
uint bufSize = (uint)Marshal.S izeOf(mfd);
uint size = 0;
bool fResult = DeviceIoControl (
hVol,
FSConstants.FSC TL_MOVE_FILE,
p,
bufSize,
IntPtr.Zero, // no output data from this FSCTL
0,
ref size,
IntPtr.Zero);
handle.Free();
if (!fResult)
{
throw new
Exception(Marsh al.GetLastWin32 Error().ToStrin g());
}
}
finally
{
CloseHandle(hVo l);
CloseHandle(hFi le);
}
}
}
/// <summary>
/// constants lifted from winioctl.h from platform sdk
/// </summary>
internal class FSConstants
{
const uint FILE_DEVICE_FIL E_SYSTEM = 0x00000009;
const uint METHOD_NEITHER = 3;
const uint METHOD_BUFFERED = 0;
const uint FILE_ANY_ACCESS = 0;
const uint FILE_SPECIAL_AC CESS = FILE_ANY_ACCESS ;
public static uint FSCTL_GET_VOLUM E_BITMAP =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 27, METHOD_NEITHER, FILE_ANY_ACCESS );
public static uint FSCTL_GET_RETRI EVAL_POINTERS =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 28, METHOD_NEITHER, FILE_ANY_ACCESS );
public static uint FSCTL_MOVE_FILE =
CTL_CODE(FILE_D EVICE_FILE_SYST EM, 29, METHOD_BUFFERED , FILE_SPECIAL_AC CESS);
static uint CTL_CODE(uint DeviceType, uint Function, uint Method,
uint Access)
{
return ((DeviceType) << 16) | ((Access) << 14) | ((Function) <<
2) | (Method);
}
}
}
-----
I'd be very grateful for any help with this conversion that you could offer.
Thanks!
Comment