Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Low level file access with .NET

Is there any class in the .NET framework which provides access to \.\G: - style paths. (i.e. raw volumes)?

We're currently doing this without any problem using p/invoked ReadFile and WriteFile, which is not complex for synchronous access, but it's tedious to add async read/write, because of all the care you need to take over pinning and handling the OVERLAPPED structure and managing the event object lifetime, etc. (i.e. all the tedious stuff we'd have to do in Win32 code...)

It's hard to prove you've got the interaction with the GC correct too, with any simple testing technique.

The FileStream class contains all this code in, no doubt, a completely bomb-proof and refined fashion, and taking advantage of lots of internal helpers which we can't use. Unfortunately FileStream explicitly stops you opening a raw volume, so we can't use it.

Is there anything else in framework which helps avoid writing this sort of code from scratch? I've poked about in Reference Source, but nothing leaps out.

Update - we had already tried the suggestion below to avoid the check on the path type by opening the device ourselves and passing in the handle. When we try this, it blows up with the following error (note that this trace goes through the contstructor of FileStream - i.e we don't get any chance to interact with the stream at all):

System.IO.IOException: The parameter is incorrect.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.SeekCore(Int64 offset, SeekOrigin origin)
at System.IO.FileStream..ctor(SafeFileHandle handle, FileAccess access, Int32 bufferSize, Boolean isAsync)
at OurApp.USBComms.UsbDevice..ctor(Char driveLetter) in 

For reference, our CreateFile call looks like this:

var deviceName = String.Format(@"\\.\{0}:", driveLetter);

var handle = SafeNativeMethods.CreateFile(deviceName,
     0x80000000 | 0x40000000,
     FileShare.ReadWrite,
     0,
     FileMode.Open,
     (uint)FileOptions.Asynchronous | 0x20000000, // Last option is       'FILE_FLAG_NO_BUFFERING'
     IntPtr.Zero);
     if (handle.IsInvalid)
     {
        throw new IOException("CreateFile Error: " + Marshal.GetLastWin32Error());
     }

Update3: It turns out that (on a volume handle, anyway), you can't call SetFilePointer on a handle which has been opened with FILE_FLAG_OVERLAPPED. This makes some sense, as SetFilePointer is useless on files where there's any kind of multithreaded access anyway. Unfortunately FileStream seems determined to call this during construction for some reason (still trying to track down why) which is what causes the failure.

like image 325
Will Dean Avatar asked Mar 06 '15 14:03

Will Dean


People also ask

What is low-level input output?

Low-level file I/O functions allow the most direct control over reading or writing data to a file. Export to Text Data Files with Low-Level I/O. This example shows how to create text files, including combinations of numeric and character data and nonrectangular files, using the low-level fprintf function.


2 Answers

As Sriram Sakthivel noted (+1), you could pass a SafeFileHandle to the FileStream constructor.

From your stacktrace I'm assuming you tried to seek the stream to an invalid position ; raw disks / volume have special rules about read/write positions.

For instance, you cannot start reading a disk in the middle of a sector (you'll have to read/seek per chunk of 512 bytes). Try to read for instance at offset 0 to see if it work better.

like image 192
ken2k Avatar answered Oct 14 '22 03:10

ken2k


I believe you can use this constructor of FileStream passing the pre opened FileHandle as SafeFileHandle instance. With that you have managed FileStream instance which you can use to issue an async I/O operation.

public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync);

Also when you're planning to do async I/O, don't forget to set isAsnc flag to true. Otherwise you'll not get all the benefits of async I/O.

like image 2
Sriram Sakthivel Avatar answered Oct 14 '22 02:10

Sriram Sakthivel