Skip to content

Instantly share code, notes, and snippets.

@BinToss
Created May 11, 2023 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BinToss/d86eead5352f68e9f651a58449713775 to your computer and use it in GitHub Desktop.
Save BinToss/d86eead5352f68e9f651a58449713775 to your computer and use it in GitHub Desktop.
What happens if a null, invalid, or closed handle if passed to GetFileType?
#!meta
{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}}
#!csharp
/** Q: What happens if a null, invalid, or closed handle is passed to GetFileType?
A: If the handle passed to GetFileType is null, invalid (i.e. 0 or -1), or closed, the Win32Error code will be ERROR_INVALID_HANDLE (6)
*/
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
// 1. null/invalid
try
{
using SafeFileHandle hFile = new(0, true);
FILE_TYPE type = GetFileType(hFile);
Console.WriteLine(type); // unreachable
}
catch(Exception ex)
{
Console.WriteLine(ex);
/** System.ComponentModel.Win32Exception (6): The handle is invalid.
at Submission#2.GetFileType(SafeHandle hFile)
at Submission#2.<<Initialize>>d__0.MoveNext()
*/
}
// 2. closed
try
{
using FileStream fileStream = File.Open(@"C:\new.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
using SafeFileHandle hFile = new(fileStream.SafeFileHandle.DangerousGetHandle(), true);
fileStream.Close();
FILE_TYPE type = GetFileType(hFile);
Console.WriteLine(type); // unreachable
}
catch(Exception ex)
{
Console.WriteLine(ex);
/** System.ComponentModel.Win32Exception (6): The handle is invalid.
at Submission#2.GetFileType(SafeHandle hFile)
at Submission#2.<<Initialize>>d__0.MoveNext()
*/
}
#region backend
// ! NOTE: modified to throw exception when native funtion writes non-success error code to thread
/// <exception cref="Win32Exception">GetFileType encountered an error.</exception>
/// <inheritdoc cref="GetFileType(HANDLE)"/>
[SupportedOSPlatform("windows5.1.2600")]
public static unsafe FILE_TYPE GetFileType(SafeHandle hFile)
{
bool hFileAddRef = false;
try
{
if (hFile is not object)
throw new ArgumentNullException(nameof(hFile));
HANDLE hFileLocal;
hFile.DangerousAddRef(ref hFileAddRef);
hFileLocal = (HANDLE)hFile.DangerousGetHandle();
FILE_TYPE type = GetFileType(hFileLocal);
Win32Exception ex = new();
return ex.NativeErrorCode is 0 ? GetFileType(hFileLocal) : throw ex;
}
finally
{
if (hFileAddRef)
hFile.DangerousRelease();
}
}
/// <summary>Retrieves the file type of the specified file.</summary>
/// <param name="hFile">A handle to the file.</param>
/// <returns>
/// <para>The function returns one of the following values. </para>
/// <para>This doc was truncated.</para>
/// </returns>
/// <remarks>
/// <para><see href="https://docs.microsoft.com/windows/win32/api//fileapi/nf-fileapi-getfiletype">Learn more about this API from docs.microsoft.com</see>.</para>
/// </remarks>
[DllImport("KERNEL32.dll", ExactSpelling = true, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SupportedOSPlatform("windows5.1.2600")]
public static extern FILE_TYPE GetFileType(HANDLE hFile);
public readonly partial struct HANDLE : IEquatable<HANDLE>
{
public readonly IntPtr Value;
public HANDLE(IntPtr value) => this.Value = value;
public static HANDLE Null => default;
public bool IsNull => Value == default;
public static implicit operator IntPtr(HANDLE value) => value.Value;
public static explicit operator HANDLE(IntPtr value) => new HANDLE(value);
public static bool operator ==(HANDLE left, HANDLE right) => left.Value == right.Value;
public static bool operator !=(HANDLE left, HANDLE right) => !(left == right);
public bool Equals(HANDLE other) => this.Value == other.Value;
public override bool Equals(object obj) => obj is HANDLE other && this.Equals(other);
public override int GetHashCode() => this.Value.GetHashCode();
}
public enum FILE_TYPE : uint
{
FILE_TYPE_UNKNOWN = 0U,
FILE_TYPE_DISK = 1U,
FILE_TYPE_CHAR = 2U,
FILE_TYPE_PIPE = 3U,
FILE_TYPE_REMOTE = 32768U,
}
#endregion backend
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment