A little C# -> VB.Net conversion help?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jim Hubbard

    A little C# -> VB.Net conversion help?

    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!




  • Herfried K. Wagner [MVP]

    #2
    Re: A little C# -&gt; VB.Net conversion help?

    "Jim Hubbard" <reply@groups.p lease> schrieb:[color=blue]
    >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.[/color]

    Converting code between .NET programming languages
    <URL:http://dotnet.mvps.org/dotnet/faqs/?id=languagecon verters&lang=en >

    --
    M S Herfried K. Wagner
    M V P <URL:http://dotnet.mvps.org/>
    V B <URL:http://dotnet.mvps.org/dotnet/faqs/>


    Comment

    • Jim Hubbard

      #3
      Re: A little C# -&gt; VB.Net conversion help?

      Thanks for the links.

      I tried all of the free converters, and all of the failed.

      There were 2 here I had not seen before. The best of the free converters is
      at http://authors.aspalliance.com/aldot...translate.aspx .

      Although it also failed to convert the code, it is more verbose in the
      reasons why.



      "Herfried K. Wagner [MVP]" <hirf-spam-me-here@gmx.at> wrote in message
      news:OTHVTpu6EH A.2568@TK2MSFTN GP10.phx.gbl...[color=blue]
      > "Jim Hubbard" <reply@groups.p lease> schrieb:[color=green]
      >>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.[/color]
      >
      > Converting code between .NET programming languages
      > <URL:http://dotnet.mvps.org/dotnet/faqs/?id=languagecon verters&lang=en >
      >
      > --
      > M S Herfried K. Wagner
      > M V P <URL:http://dotnet.mvps.org/>
      > V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
      >[/color]


      Comment

      • Frans Bouma [C# MVP]

        #4
        Re: A little C# -&gt; VB.Net conversion help?

        Jim Hubbard wrote:[color=blue]
        > 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.....[/color]

        I wouldn't call that 'short' ;)
        [color=blue]
        > I'd be very grateful for any help with this conversion that you could offer.[/color]

        It would be great if you could point out the problem area's. Converting
        C# to VB.NET is easy, and you should use one of the on-line conversion
        sites for that. It can be that these sites/tools choke on small
        constructs, (as you use win32 code, it might be the case) so you then
        should convert these small constructs by hand. If that gives problems,
        post THOSE constructs so people here can help you with these.

        Another tip: don't bother converting, as it will not gain you anything
        (it will only waste your time). Why don't you put this code into a
        library and use that one in VB.NET?

        Frans

        --
        ------------------------------------------------------------------------
        Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
        My .NET blog: http://weblogs.asp.net/fbouma
        Microsoft MVP (C#)
        ------------------------------------------------------------------------

        Comment

        Working...