How to write to raw disk file using CreateFile from kernel32.dll

-1

I'm trying to write directly to disk

I'm able to read, but I can't write.

Is there some specific function to write to file?

How to enable writing?

pinvoke´s signature:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeFileHandle CreateFile(
    string lpFileName,
    int dwDesiredAccess,
    int dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    SafeFileHandle hTemplateFile);

Reading works fine:

SafeFileHandle h = CreateFile(
    "\\.\PhysicalDrive1",
    unchecked((int)(0x80000000)),
    0,
    IntPtr.Zero,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    new SafeFileHandle(IntPtr.Zero, true));
FileStream stream = new FileStream(h, FileAccess.Read);
var @byte = stream.ReadByte();
stream.Close();
h.Close();

But not writing:

SafeFileHandle h = CreateFile(
    "\\.\PhysicalDrive1", // Be careful to not damage your HDD
    unchecked((int)(0x40000000)),
    0,
    IntPtr.Zero,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    new SafeFileHandle(IntPtr.Zero, true));

FileStream stream = new FileStream(h, FileAccess.Write);

stream.WriteByte((byte)0xFF);
h.Close();

I am doing something wrong?


The code rewritten printing last error codes:

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace RawHD
{
    static class Program
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern SafeFileHandle CreateFile(
            string lpFileName,
            int dwDesiredAccess,
            int dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            SafeFileHandle hTemplateFile);

        internal const int SHARE_NONE = 0;
        internal const int GENERIC_READ = unchecked((int)0x80000000);
        internal const int GENERIC_WRITE = unchecked((int)0x40000000);
        internal const int OPEN_EXISTING = 3;
        internal const int FILE_ATTRIBUTE_NORMAL = 0x80;

        [STAThread]
        static void Main()
        {
            SafeFileHandle fileHandle = CreateFile(
                "\\\\.\\PhysicalDrive4",
                GENERIC_WRITE,
                SHARE_NONE,
                IntPtr.Zero, // optional parameter
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                new SafeFileHandle(IntPtr.Zero, true));

            Console.WriteLine("After opening first file: " + Marshal.GetLastWin32Error());

            FileStream stream = new FileStream(fileHandle, FileAccess.Write);
            stream.WriteByte((byte)'C');
            Console.WriteLine("After writing: " + Marshal.GetLastWin32Error());
            Console.WriteLine("Char Written: C");

            fileHandle.Close();
            Console.WriteLine("After closing first file: " + Marshal.GetLastWin32Error());

            fileHandle = CreateFile(
                "\\\\.\\PhysicalDrive4",
                GENERIC_READ,
                SHARE_NONE,
                IntPtr.Zero, // optional parameter
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                new SafeFileHandle(IntPtr.Zero, true));


            Console.WriteLine("After opening second file: " + Marshal.GetLastWin32Error());
            stream = new FileStream(fileHandle, FileAccess.Read);
            var @byte = stream.ReadByte();
            Console.WriteLine("After reading: " + Marshal.GetLastWin32Error());
            Console.WriteLine("Char Read: " + (char)@byte);
            stream.Close();
            fileHandle.Close();
            Console.WriteLine("After closing second file: " + Marshal.GetLastWin32Error());

            Console.ReadKey();
        }
    }
}

This gives me this output:

After opening first file: 0

After writing: 0

Char Written: C

After closing first file: 0

After opening second file: 0

After reading: 0

Char Read: 3

After closing second file: 0


Also tried using WriteFile function from kernel32.dll:

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace RawHD
{
    static class Program
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern SafeFileHandle CreateFile(
            string lpFileName,
            int dwDesiredAccess,
            int dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            SafeFileHandle hTemplateFile);

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool WriteFile(
            SafeFileHandle hFile,
            byte[] lpBuffer,
            uint nNumberOfBytesToWrite,
            out uint lpNumberOfBytesWritten,
            [In] ref NativeOverlapped lpOverlapped);

        internal const int SHARE_NONE = 0;
        internal const int GENERIC_READ = unchecked((int)0x80000000);
        internal const int GENERIC_WRITE = unchecked((int)0x40000000);
        internal const int OPEN_EXISTING = 3;
        internal const int FILE_ATTRIBUTE_NORMAL = 0x80;

        [STAThread]
        static void Main()
        {
            SafeFileHandle fileHandle = CreateFile(
                "\\\\.\\PhysicalDrive4",
                GENERIC_WRITE,
                SHARE_NONE,
                IntPtr.Zero, // optional parameter
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                new SafeFileHandle(IntPtr.Zero, true));

            Console.WriteLine("After opening first file: " + Marshal.GetLastWin32Error());

            NativeOverlapped over = new NativeOverlapped();
            over.OffsetLow = 0;
            over.OffsetHigh = 0;

            uint written;

            WriteFile(fileHandle, Encoding.ASCII.GetBytes("Test"), 4, out written, ref over);

            Console.WriteLine("After using WriteFile: " + Marshal.GetLastWin32Error());

            fileHandle.Close();
            Console.WriteLine("After closing first file: " + Marshal.GetLastWin32Error());

            Console.ReadKey();
        }
    }
}

But this gives me error 87:

After opening first file: 0

After using WriteFile: 0

After closing first file: 87

c#
io
pinvoke
asked on Stack Overflow Apr 29, 2020 by Edney • edited Jun 20, 2020 by Community

1 Answer

0

There are no exceptions on the code, you need to use WriteAsync e ReadAsync as these functions do not support synchronous operations.

answered on Stack Overflow Apr 30, 2020 by Edney

User contributions licensed under CC BY-SA 3.0