Reputation: 197
I'm having a problem with kernal32 Pinvoke functions as they keeps throwing an INVALID_FILE_HANDLE. The program reads the first sector of the current hard disk. I can't see what is wrong with the following code.
class Program
{
const uint GENERIC_READ = 0x80000000;
const uint FILE_SHARE_READ = 0x00000001;
const uint OPEN_EXISTING = 0x00000003;
const uint FILE_FLAG_DELETE_ON_CLOSE = 0x04000000;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeFileHandle CreateFile(string Disk, uint Access, uint ShareMode, IntPtr SecurityAttributes, uint CreationDisposition, uint Flags, IntPtr TemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SetFilePointer([In] SafeFileHandle Handle, [In] int DistanceToMove, [Out] out int DistanceToMoveHigh, [In] int MoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
unsafe public static extern int ReadFile(SafeFileHandle Handle, [Out] byte[] Buffer, int NumberOfBytesToRead, out int NumberOfBytesRead, IntPtr Overlapped);
unsafe public static void Main(string[] args)
{
string Drive = @"\\.\C";
int SectorSize = 512;
int Sector = 0;
int BytesRead, DistanceToMoveHigh;
byte[] Buffer = new byte[SectorSize];
SafeFileHandle Handle = CreateFile(Drive, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, IntPtr.Zero);
SetFilePointer(Handle, Sector * SectorSize, out DistanceToMoveHigh, 0);
ReadFile(Handle, Buffer, SectorSize, out BytesRead, IntPtr.Zero);
Console.WriteLine(Marshal.GetLastWin32Error()); // It gives 6 which translates to an INVALID_FILE_HANDLE error
Console.ReadKey();
}
}
Upvotes: 0
Views: 1099
Reputation: 612854
Your call to CreateFile
fails. Of course you cannot know that because you omitted any error checking. Read the documentation. Errors for all three functions that you call are signaled by the return value. Which you ignore.
Your call to CreateFile
returns INVALID_HANDLE_VALUE
. You need to test for that. When you encounter that, and only then, call GetLastWin32Error
. Likely ERROR_ACCESS_DENIED
will be returned then.
FILE_FLAG_DELETE_ON_CLOSE
is a mistake. Remove that flag.FILE_SHARE_READ | FILE_SHARE_WRITE
. @"\\.\C:"
with a trailing colon. Upvotes: 3
Reputation: 43876
You use GetLastWin32Error
in a wrong way.
The method that fails here is CreateFile
and it returns an INVALID_HANDLE_VALUE
(indicating that it failed). To determine what went wrong you have to call GetLastWin32Error
directly after CreateFile
.
When you call it after trying to read, the error is of course ERROR_INVALID_HANDLE (6)
as you passed an invalid handle to ReadFile
.
If you call GetLastWin32Error
directly after the failing CreateFile
you get error 2:
The system cannot find the file specified.
That is because the the drive name misses a :
string Drive = @"\\.\C:"; // <- add colon :
I tried with that drive name, but then got the error 32:
The process cannot access the file because it is being used by another process.
I keep trying to figure out how that can be handled...
Upvotes: 0