4

I'm trying to create a safe file handle for "C:" using the CreateFile method of kernel32.dll which always returns me an invalid handle.

Any help on what am i doing wrong here?"C:

CreateFile(
    lpFileName: "C:",
    dwDesiredAccess: FileAccess.ReadWrite,
    dwShareMode: FileShare.ReadWrite,
    lpSecurityAttributes: IntPtr.Zero,
    dwCreationDisposition: FileMode.OpenOrCreate,
    dwFlagsAndAttributes: FileAttributes.Normal,
    hTemplateFile: IntPtr.Zero);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern SafeFileHandle CreateFile(
    string lpFileName,
    [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
    [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
    IntPtr lpSecurityAttributes,
    [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
    [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
    IntPtr hTemplateFile);
Steve
  • 7,171
  • 2
  • 30
  • 52

2 Answers2

4

There are a couple of parameters not quite right.

  1. To open a volume, you must prefix the drive letter with \\.\.
  2. You can only open the volume with read privileges.

Try this code:

SafeFileHandle handle = CreateFile(
    lpFileName: @"\\.\C:",
    dwDesiredAccess: FileAccess.Read,
    dwShareMode: FileShare.ReadWrite,
    lpSecurityAttributes: IntPtr.Zero,
    dwCreationDisposition: FileMode.OpenOrCreate,
    dwFlagsAndAttributes: FileAttributes.Normal,
    hTemplateFile: IntPtr.Zero );

Note that to open a volume handle with read privileges, you must be running as an administrator, otherwise you will get access denied (error code 5). As Nik Bougalis and the CreateFile documentation points out, if you specify dwDesiredAccess as 0 administrator privileges are not required.

If this parameter is zero, the application can query certain metadata such as file, directory, or device attributes without accessing that file or device, even if GENERIC_READ access would have been denied.

Steve
  • 7,171
  • 2
  • 30
  • 52
  • Even if you are not running as an administrator you can try to open the volume with `0` for `dwDesiredAccess`. Per the [`CreateFile` page on MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx): "The `dwDesiredAccess` parameter can be zero, allowing the application to query device attributes without accessing a device. This is useful [...] for reading statistics without requiring higher-level data read/write permission." The returned handle is, as explained, **severely** limited, but this way you can get around the need for admin access for routine queries. – Nik Bougalis May 21 '13 at 21:39
  • 1
    @NikBougalis thanks for pointing that out. I've updated my answer to reflect that. – Steve May 21 '13 at 21:45
2

This is how i resolved the issue

    private const int GENERIC_READ = unchecked((int)0x80000000);
    private const int FILE_SHARE_READ = 1;
    private const int FILE_SHARE_WRITE = 2;
    private const int OPEN_EXISTING = 3;
    private const int IOCTL_DISK_GET_DRIVE_LAYOUT_EX = unchecked((int)0x00070050);
    private const int ERROR_INSUFFICIENT_BUFFER = 122;
    NativeMethods.CreateFile("\\\\.\\PHYSICALDRIVE" + PhysicalDrive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))