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.