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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With