Click here to Skip to main content
14,452,204 members
Rate this:
Please Sign up or sign in to vote.
See more:
Hi everyone, first of all i've got to say that this forum is great!
Well, this is my problem: I'm writing an application in VB.NET, and one of the features include showing the partitions in the hard drive(s). Unfortunately, VB.NET can't acces disk data in such a low level, that's why I'm creating a small DLL in other language (C#) to access that data through a function inside the DLL.
I've searched a lot, and i've found the CreateFile function and i've added it to my project. So far, everything seems to be Ok.

When I test my project, the output is completely different of what it should be.
This is the hexadecimal output of the raw reading of my first physical drive using HxD
FA 33 C0 8E D8 8E C0 8E D0 BC 00 7C FB 8B F4 BF 
00 06 B9 00 02 FC F2 A4 EA 1D 06 00 00 A0 17 04 
A8 0F 75 03 E8 B6 00 BE BE 07 B9 04 00 80 3C 80 
74 0B 83 C6 10 E2 F6 BE 6B 01 E8 36 00 8B EE E8 
64 00 73 06 BE 83 01 E8 29 00 81 3E FE 7D 55 AA 
74 06 BE 94 01 E8 1B 00 B2 80 8B F5 EA 00 7C 00 
00 81 C6 00 06 33 DB B4 0E AC 0A C0 74 04 CD 10 
EB F7 C3 E8 EB FF 32 E4 CD 16 CD 18 BF 05 00 B8 
01 02 CD 13 73 08 33 C0 CD 13 4F 75 F2 F9 C3 BF 
05 00 BE 5B 07 B2 80 B4 42 CD 13 73 08 33 C0 CD 
13 4F 75 EE F9 C3 BB AA 55 B2 80 B4 41 CD 13 72 
1A 81 FB 55 AA 75 14 F7 C1 01 00 74 0E 83 C6 08 
BF 63 07 FC A5 A5 E8 C6 FF EB 11 33 DB 8E C3 BB 
00 7C 8B 14 8B 4C 02 B2 80 E8 A0 FF C3 8B 0E A4 
07 E3 77 8B 0E A6 07 E3 71 83 F9 3C 77 6C 8B 0E 
A8 07 E3 66 81 F9 00 78 77 60 8B 0E AA 07 E3 5A 
BE 04 00 BB 00 10 8E C3 BB 00 01 BA 80 00 8B CE 
E8 69 FF 72 45 46 81 C3 00 02 FF 0E A6 07 75 EB 
33 DB B2 5A BE 00 01 8B FE 8B 0E A8 07 FC 1E 06 
1F D0 CA D0 CA D0 CA D0 CA FE C2 AC 32 C2 AA 32 
E4 03 D8 E2 EC 1F 3B 1E A4 07 72 0E FA 8C CC 8E 
D4 BC FE FF FB EA 00 01 00 10 C3 10 00 01 00 00 
7C 00 00 00 00 00 00 00 00 00 00 49 6E 76 61 6C 
69 64 20 70 61 72 74 69 74 69 6F 6E 20 74 61 62 
6C 65 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E 67 
20 4F 53 00 4D 69 73 73 69 6E 67 20 4F 53 00 00 
00 00 00 00 36 B3 37 00 04 6D 00 00 48 49 00 00 
00 00 00 00 00 2C 49 6E F7 3A 0C 00 00 00 80 20 
21 00 07 A5 D5 50 00 08 00 00 00 00 D0 00 00 A5 
D6 50 07 FE FF FF 00 08 D0 00 00 98 29 01 00 FE 
FF FF 07 FE FF FF 00 A0 F9 01 00 E0 A5 01 00 FE 
FF FF 05 FE FF FF 00 80 9F 03 00 30 09 01 55 AA

As you can see everything is fine, since the last two bytes are the magic number (0x55AA) and the bold text is exacly what I want: the partition table.
However, the code i'm testing shows this output:
8B C6 BF C3 80 C3 BF C3 00 0E FA BF 0E 75 81 08 
FA C0 01 FA C0 AA E3 F9 F9 A0 C0 FA FA 13 A4 D8 
55 BF FF 8E 71 14 FA C6 C6 8E 01 D8 FA 01 00 01 
EB 7C 13 E8 00 77 00 C6 C0 33 71 F6 FA 75 8B 71 
06 FA E8 C0 C6 13 33 71 07 FA 02 EE E3 05 E8 80 
EB C0 C6 07 33 71 00 FA FB 01 75 F9 F9 FA BF FA 
FA 02 E8 FA C0 C6 FF AA F4 41 00 BF EB D8 8E 00 
3C 78 FC 71 3C 5A 83 0E 8E F2 8E EA 08 8E FA C1 
33 C0 8E 00 E8 D0 C6 BF 8E 00 AA FF E3 60 FC 08 
8E FA C6 F5 8E FB 01 AA 73 8E 00 E8 D0 C6 BF 8E 
00 AA FF 8B 60 FC 74 80 E8 FB 01 AA 00 8E 00 C3 
06 02 0E E8 80 FF 02 78 63 33 FA EB F4 13 E8 D0 
08 00 8E AA C3 C3 71 E8 5A 3C 06 C6 FF C3 FC 74 
FA BF 75 02 75 FE C0 FB 01 71 13 5A FC 75 F4 F9 
8E 8B E4 75 F4 BB 8E 8B F7 13 60 00 E4 74 75 F4 
55 8E 8B DB 02 60 FA CD E4 00 75 F4 80 8E 8B 8B 
C6 D8 FA 74 FA 00 C3 FC 74 FA 33 00 01 FA 75 C3 
71 AC 5A C3 83 01 02 FC FA C0 5A F4 BB 8E FF 3C 
C6 FF FB 8B C6 FA 33 75 E3 75 F4 55 8E AA 17 C0 
04 00 11 00 11 00 11 00 11 E3 07 41 83 07 80 83 
0E 8E 80 77 77 04 36 17 F9 8E C3 F4 8B F2 DB C3 
8B 0E E3 5A 0E F9 FA 33 FA 00 FC 00 FA 33 FA FA 
BF FA FA FA FA FA FA FA FA FA FA 00 CD 32 81 74 
AC 06 A8 EB 81 C3 EB AC EB AC 10 CD A8 EB 81 C6 
74 33 FA 83 C3 C3 10 C3 A8 74 10 81 06 AC CD B4 
A8 AA 94 FA 7D AC E8 E8 AC CD B4 A8 AA 94 FA FA 
FA FA FA FA F6 55 BE FA D8 04 FA FA 29 00 FA FA 
FA FA FA FA FA 00 00 CD 78 E8 FB FA FA FA 01 A8 
0F FA 8E C3 4C 74 FA D0 FA FA FA FA 00 FA FA C3 
02 74 8E E3 5A 5A FA D0 00 FA FA 42 07 33 FA E3 
5A 5A 8E E3 5A 5A FA 13 60 33 FA 07 C3 33 FA E3 
5A 5A 8E E3 5A 5A FA 01 CD 8E FA 74 BC 33 E8 80 

It's pretty obvious this is wrong, and i can't figure out what's doing that.

SOME EXTRA DATA:

- I'm a VB.NET programmer, so I'm not too familiar (yet) with C# functions and syntaxis
- My physical drives have been formatted and partitioned with GParted in Ubuntu 12.04
- My code is down here [the code in class1.cs is not mine, but honestly i can't remember where in found it so, if it's yours, thanks :) ]

CLASS1.CS
using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace RAW
{
    public class DISK
    {
        public struct streamer
        {
            public System.IO.Stream STR;
            public Microsoft.Win32.SafeHandles.SafeFileHandle SH;
            public bool isERROR;
        }

        const int maxretry = 6;

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFile(string lpFileName,
        FileAccess dwDesiredAccess, FileShare dwShareMode,
        uint lpSecurityAttributes, FileMode dwCreationDisposition, uint
        dwFlagsAndAttributes,
        uint hTemplateFile);

        public static unsafe streamer CreateStream(string drive, FileAccess type)
        {
            streamer retVal = new streamer();
            int retries = 0;
            Microsoft.Win32.SafeHandles.SafeFileHandle h;

        tryagain:
            h = CreateFile(/* @"\\.\"+ */drive + "", type, FileShare.None, 0, FileMode.Open, 0, 0);
            if (h.IsInvalid)
            {
                retries++;
                if (retries > maxretry)
                {
                    retVal.isERROR = true;
                    return retVal;
                }
                goto tryagain;
            }

            if (!h.IsInvalid)
            {
                System.IO.Stream inPutFile = new FileStream(h, type);
                retVal.SH = h;
                retVal.STR = inPutFile;
                retVal.isERROR = false;
                return retVal;
            }
            else
            {
                retVal.isERROR = true;
                return retVal;
            }
        }
        /*
        When reading a sector.. example: NTFS uses 512 bytes pr sector, u can read as many bytes u 
        wish from a specific sector and sectors ahead, start sector must always be a multiply of 512.. 
        f.eks a start sector of 2 will throw an exeption.
        while start of 0, 512 or 1024 and so on is ok
        You can start at sector 512 and only read 2 bytes if you wish.
        This is true for both Read and Write functions
        Bytes pr sector is stored in sector 0
        DW      512             ; 0x0B - Bytes/sector
        */

        // use streamer.STR to read write data depending on what mode you created it in.

        public static unsafe byte[] ReadSector(int startingsector, int numberofsectors, streamer iface)
        {
            byte[] b = new byte[numberofsectors];
            if (!iface.SH.IsInvalid)
            {
                if (iface.STR.CanRead)
                {
                    //b = 0; // [numberofsectors];
                    iface.STR.Seek(startingsector, SeekOrigin.Begin);
                    iface.STR.Read(b, 0, numberofsectors);
                    return b;
                }
            }
            return null;
        }

        public static unsafe int WriteSector(int startingsector, int numberofsectors, byte[] data, streamer iface)
        {
            if (!iface.SH.IsInvalid)
            {
                if (iface.STR.CanRead)
                {
                    iface.STR.Seek(startingsector, SeekOrigin.Begin);
                    iface.STR.Write(data, 0, numberofsectors);
                    iface.STR.Flush();
                    return 0;
                }
            }
            return -1;
        }

        public static unsafe bool DropStream(streamer iface)
        {
            try
            {
                iface.STR.Close();
                iface.SH.Close();
                return true;
            }
            catch (Exception)
            {
                return false;
                throw;
            }
        }
    }
}


FORM1.CS (inside this Form there are two textboxes (textbox1 and txt) and a button)

using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace wap1
{
    public partial class Form1 : Form
    {
        
        public Form1()
        {
            InitializeComponent();
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            RAW.DISK.streamer myStream = RAW.DISK.CreateStream(txt.Text, FileAccess.Read);
            byte[] b = RAW.DISK.ReadSector(0, 512, myStream);
            RAW.DISK.DropStream(myStream);
            textBox1.Text = ByteArrayToHexString(b, " ");
        }
        /// <summary>
        /// Function converts byte array to it's hexadecimal implementation
        /// </summary>
        /// <param name="ArrayToConvert">Array to be converted</param>
        /// <param name="Delimiter">Delimiter to be inserted between bytes</param>
        /// <returns>String to represent given array</returns>
        public static string ByteArrayToHexString(byte[] ArrayToConvert, string Delimiter)
        {
            int LengthRequired = (ArrayToConvert.Length + Delimiter.Length) * 6;
            StringBuilder tempstr = new StringBuilder(LengthRequired, LengthRequired);
            foreach (byte CurrentElem in ArrayToConvert)
            {
                StringBuilder str = new StringBuilder(3, 3);
                str.Append(ArrayToConvert[CurrentElem]);
                int number = int.Parse(str.ToString());
                string hex1 = number.ToString("x2");
                string hex = hex1.ToUpper();
                tempstr.Append(hex);
                tempstr.Append(Delimiter);
            }
            return tempstr.ToString();
        }
    }
}


If you have some other ideas or code samples or links or whatever that can help me read the first sector of my physical drive PLEASE post it here, since that HEX code is all i need (i know how to use it :D)

THANKS!

Pd. I'm sorry if my message is too long, but i really need to solve this issue since it has been bugging me for the last 2 months!
Posted

1 solution

Rate this:
Please Sign up or sign in to vote.

Solution 1

its seems like ByteArrayToHexString method is the culprit.

replace it with the following code and try:

public static string ByteArrayToHexString(byte[] ba)
{
  StringBuilder hex = new StringBuilder(ba.Length * 2);
  foreach (byte b in ba)
    hex.AppendFormat("{0:x2}", b);
  return hex.ToString();
}
   
Comments
Genaro de Pomar 28-Aug-12 0:25am
   
THANK YOU very much! It worked perfectly!
I was thinking that was something inside that method, but since I'm not familiar with that language...
Anyway thank you very much!
Kuthuparakkal 28-Aug-12 0:28am
   
You mare most welcome. And am glad that you got it working!!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100