I\'m developing an application which needs to interact with Video4Linux abstraction. The application is developed in C#, using the mono framework.
The problem I\'m f
Example usage:
Capability capability;
if (UnsafeNativeMethods.Ioctl(handle, request, ref capability) == -1)
{
throw new UnixIOException();
}
Capability:
[StructLayout(LayoutKind.Sequential, Size = 104)]
internal struct Capability
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Driver;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Device;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string BusInfo;
public uint Version;
public CapabilityFlags Capabilities;
}
UnsafeNativeMethods:
internal static class UnsafeNativeMethods
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport("libc", EntryPoint = "close", SetLastError = true)]
internal static extern int Close(IntPtr handle);
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
internal static extern int Ioctl(SafeUnixHandle handle, uint request, ref Capability capability);
[DllImport("libc", EntryPoint = "open", SetLastError = true)]
internal static extern SafeUnixHandle Open(string path, uint flag, int mode);
internal static string Strerror(int error)
{
try
{
var buffer = new StringBuilder(256);
var result = Strerror(error, buffer, (ulong)buffer.Capacity);
return (result != -1) ? buffer.ToString() : null;
}
catch (EntryPointNotFoundException)
{
return null;
}
}
[DllImport("MonoPosixHelper", EntryPoint = "Mono_Posix_Syscall_strerror_r", SetLastError = true)]
private static extern int Strerror(int error, [Out] StringBuilder buffer, ulong length);
}
SafeUnixHandle:
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal sealed class SafeUnixHandle : SafeHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private SafeUnixHandle()
: base(new IntPtr(-1), true)
{
}
public override bool IsInvalid
{
get { return this.handle == new IntPtr(-1); }
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return UnsafeNativeMethods.Close(this.handle) != -1;
}
}
UnixIOException:
[Serializable]
public class UnixIOException : ExternalException
{
private readonly int nativeErrorCode;
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
public UnixIOException()
: this(Marshal.GetLastWin32Error())
{
}
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
public UnixIOException(int error)
: this(error, GetErrorMessage(error))
{
}
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
public UnixIOException(string message)
: this(Marshal.GetLastWin32Error(), message)
{
}
public UnixIOException(int error, string message)
: base(message)
{
this.nativeErrorCode = error;
}
public UnixIOException(string message, Exception innerException)
: base(message, innerException)
{
}
protected UnixIOException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
this.nativeErrorCode = info.GetInt32("NativeErrorCode");
}
public int NativeErrorCode
{
get { return this.nativeErrorCode; }
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("NativeErrorCode", this.nativeErrorCode);
base.GetObjectData(info, context);
}
private static string GetErrorMessage(int error)
{
var errorDescription = UnsafeNativeMethods.Strerror(error);
return errorDescription ?? string.Format("Unknown error (0x{0:x})", error);
}
}