[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
IntPtr lpInBuffer, uint nInBufferSize,
IntPtr lpOutBuffer, uint nOutBufferSize,
out uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DeviceIoControl( IntPtr hDevice, uint dwIoControlCode, ref long InBuffer,
int nInBufferSize, ref long OutBuffer, int nOutBufferSize,
ref int pBytesReturned, [In] ref NativeOverlapped lpOverlapped);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern bool DeviceIoControl(
Microsoft.Win32.SafeHandles.SafeFileHandle hDevice,
EIOControlCode IoControlCode,
[MarshalAs(UnmanagedType.AsAny)]
[In] object InBuffer,
uint nInBufferSize,
[MarshalAs(UnmanagedType.AsAny)]
[out] object OutBuffer,
uint nOutBufferSize,
ref uint pBytesReturned,
[In] ref System.Threading.NativeOverlapped Overlapped
);
<DllImport("kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function DeviceIoControl(ByVal hDevice As IntPtr, _
ByVal dwIoControlCode As Int32, ByVal lpInBuffer As IntPtr, _
ByVal nInBufferSize As Int32, ByVal lpOutBuffer As IntPtr, _
ByVal nOutBufferSize As Int32, ByRef lpBytesReturned As Int32, _
ByVal lpOverlapped As System.Threading.NativeOverlapped) As Boolean
End Function
None.
hDevice - To retrieve a handle to a volume, call CreateFile with the lpFileName parameter set to a string of the following form: \\.\DriveLetter:. DriveLetter is not case-sensitive and does not require a colon after it.
Example:
tHandle = CreateFile(@"\\.\C:", FileAccess.Read, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)
lpOverlapped - Main use in asynchronous deviceIoControl. NativeOverlapped is the managed version of the structure and use is the same. The difference between NativeOverlapped and Overlapped is managed Struct vs managed Class respectively. NativeOverlapped was more condusive for one-way device driver communication. Convert from Overlapped to NativeOverlapped to make the call, since NativeOverlapped is explicitly defined to mimic the unmanaged Overlapped structure.
This is great for interacting with devices; now perhaps someone can help with the SetupDi calls to actually discover the device handles, etc...? If you are able to conquer it (I wasn't) toss me a mail at dotnet at richardgoodwin dot com
-
Pin your NativeOverlapped structure, DeviceIoControl is asynchronous and will write into the overlapped structure upon completion of IO requested. If you NativeOverlapped structure has been moved by garbage collection it will write into the wrong area causing heap corruption.
-
If you want x64 proccessor support, you CANNOT use the System.Threading.NativeOverlapped structure as a ref parameter described above. The overlap structure must be allocated in global memory space. See the section "DeviceIoControl w/x64 support":
Regards,
Travis
-
Public ReadOnly Property CardID() As String
Get
Dim dwErrorCode As FarcConstants
Dim dwBytesReceived As Int32
Dim ip As IntPtr = Marshal.AllocHGlobal(13)
Dim erg As String
If DeviceIoControl(hDriver, IOCTL_FARC_GET_CARDID, Nothing, 0, ip, 13, dwBytesReceived, Nothing) Then
erg = Marshal.PtrToStringAnsi(ip)
Marshal.FreeHGlobal(ip)
Else
dwErrorCode = Marshal.GetLastWin32Error
Marshal.FreeHGlobal(ip)
Throw New InvalidOperationException("Get Card ID fails. Errorcode: " & _
dwErrorCode.ToString, New System.ComponentModel.Win32Exception(dwErrorCode))
End If
Return erg
End Get
End Property
public bool DeviceIoControl( IntPtr hDevice, uint dwIoControlCode, ref long buffer, int bufferSize, ref NativeOverlapped pOverlapped)
{
int NoReturn = 0;
return DeviceIoControl( hDevice, dwIoControlCode, ref buffer, bufferSize, ref buffer, bufferSize, ref NoReturn, ref pOverlapped );
}
public bool PlxIntrAttach(IntPtr handle, PlxIntr intrType)
{
// Call to PLX card to attach wait event to an Interrupts
// Declare control code
uint Control;
DriverMsgs AttachMsg = DriverMsgs.MsgIntrAttach;
Control = CtrCode( cFileDeviceUnknown, (int)AttachMsg, cMethodBuffered, cFileAnyAccess );
// Set return variable up
bool Status = false;
// Initialize the "buffer"
long DeviceBuffer = 0;
// Fill the buffer with the interrupt bitflag
DeviceBuffer = (long)intrType;
// Call the P/Invoked function through masking method
Status = DeviceIoControl( handle, Control, ref DeviceBuffer, 8, ref AdcOverlapData );
// Return with Status
return Status;
}
public byte[] ReadRawPartition(int harddisk, int partition, int sectors)
{
var name = string.Format(
@"\\?\GLOBALROOT\Device\Harddisk{0}\Partition{1}",
harddisk, partition);
var handle = Win32.CreateFile(name, FileAccess.Read, FileShare.ReadWrite,
IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
int dummy;
var diskGeo = new DISK_GEOMETRY();
Win32.DeviceIoControl(handle, IOCTL.DISK_GET_DRIVE_GEOMETRY,
IntPtr.Zero, 0, out diskGeo, Marshal.SizeOf(diskGeo), out dummy, IntPtr.Zero);
var partInfo = new PARTITION_INFORMATION();
Win32.DeviceIoControl(handle, IOCTL.DISK_GET_PARTITION_INFO,
IntPtr.Zero, 0, out partInfo, Marshal.SizeOf(partInfo), out dummy, IntPtr.Zero);
var length = sectors * diskGeo.BytesPerSector;
var data = new byte[length];
int len;
if (!Win32.ReadFile(handle, data, length, out len, IntPtr.Zero))
return null;
if (length != len) Array.Resize(ref data, len);
return data;
}
cf. DISK_GEOMETRY, PARTITION_INFORMATION
Do you know one? Please contribute it!
using System;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
[Flags]
public enum EMethod : uint
{
Buffered = 0,
InDirect = 1,
OutDirect = 2,
Neither = 3
}
[Flags]
public enum EFileDevice : uint
{
Beep = 0x00000001,
CDRom = 0x00000002,
CDRomFileSytem = 0x00000003,
Controller = 0x00000004,
Datalink = 0x00000005,
Dfs = 0x00000006,
Disk = 0x00000007,
DiskFileSystem = 0x00000008,
FileSystem = 0x00000009,
InPortPort = 0x0000000a,
Keyboard = 0x0000000b,
Mailslot = 0x0000000c,
MidiIn = 0x0000000d,
MidiOut = 0x0000000e,
Mouse = 0x0000000f,
MultiUncProvider = 0x00000010,
NamedPipe = 0x00000011,
Network = 0x00000012,
NetworkBrowser = 0x00000013,
NetworkFileSystem = 0x00000014,
Null = 0x00000015,
ParellelPort = 0x00000016,
PhysicalNetcard = 0x00000017,
Printer = 0x00000018,
Scanner = 0x00000019,
SerialMousePort = 0x0000001a,
SerialPort = 0x0000001b,
Screen = 0x0000001c,
Sound = 0x0000001d,
Streams = 0x0000001e,
Tape = 0x0000001f,
TapeFileSystem = 0x00000020,
Transport = 0x00000021,
Unknown = 0x00000022,
Video = 0x00000023,
VirtualDisk = 0x00000024,
WaveIn = 0x00000025,
WaveOut = 0x00000026,
Port8042 = 0x00000027,
NetworkRedirector = 0x00000028,
Battery = 0x00000029,
BusExtender = 0x0000002a,
Modem = 0x0000002b,
Vdm = 0x0000002c,
MassStorage = 0x0000002d,
Smb = 0x0000002e,
Ks = 0x0000002f,
Changer = 0x00000030,
Smartcard = 0x00000031,
Acpi = 0x00000032,
Dvd = 0x00000033,
FullscreenVideo = 0x00000034,
DfsFileSystem = 0x00000035,
DfsVolume = 0x00000036,
Serenum = 0x00000037,
Termsrv = 0x00000038,
Ksec = 0x00000039
}
[Flags]
public enum EIOControlCode : uint
{
// STORAGE
StorageBase = EFileDevice.MassStorage,
StorageCheckVerify = (StorageBase<<16) | (0x0200<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageCheckVerify2 = (StorageBase<<16) | (0x0200<<2) | EMethod.Buffered | (0<<14), // FileAccess.Any
StorageMediaRemoval = (StorageBase<<16) | (0x0201<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageEjectMedia = (StorageBase<<16) | (0x0202<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageLoadMedia = (StorageBase<<16) | (0x0203<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageLoadMedia2 = (StorageBase<<16) | (0x0203<<2) | EMethod.Buffered | (0<<14),
StorageReserve = (StorageBase<<16) | (0x0204<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageRelease = (StorageBase<<16) | (0x0205<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageFindNewDevices = (StorageBase<<16) | (0x0206<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageEjectionControl = (StorageBase<<16) | (0x0250<<2) | EMethod.Buffered | (0<<14),
StorageMcnControl = (StorageBase<<16) | (0x0251<<2) | EMethod.Buffered | (0<<14),
StorageGetMediaTypes = (StorageBase<<16) | (0x0300<<2) | EMethod.Buffered | (0<<14),
StorageGetMediaTypesEx = (StorageBase<<16) | (0x0301<<2) | EMethod.Buffered | (0<<14),
StorageResetBus = (StorageBase<<16) | (0x0400<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageResetDevice = (StorageBase<<16) | (0x0401<<2) | EMethod.Buffered | (FileAccess.Read<<14),
StorageGetDeviceNumber = (StorageBase<<16) | (0x0420<<2) | EMethod.Buffered | (0<<14),
StoragePredictFailure = (StorageBase<<16) | (0x0440<<2) | EMethod.Buffered | (0<<14),
StorageObsoleteResetBus = (StorageBase<<16) | (0x0400<<2) | EMethod.Buffered | ((FileAccess.Read | FileAccess.Write)<<14),
StorageObsoleteResetDevice = (StorageBase<<16) | (0x0401<<2) | EMethod.Buffered | ((FileAccess.Read | FileAccess.Write)<<14),
// DISK
DiskBase = EFileDevice.Disk,
DiskGetDriveGeometry = (DiskBase<<16)|(0x0000<<2)|EMethod.Buffered|(0<<14),
DiskGetPartitionInfo = (DiskBase<<16)|(0x0001<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskSetPartitionInfo = (DiskBase<<16)|(0x0002<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskGetDriveLayout = (DiskBase<<16)|(0x0003<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskSetDriveLayout = (DiskBase<<16)|(0x0004<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskVerify = (DiskBase<<16)|(0x0005<<2)|EMethod.Buffered|(0<<14),
DiskFormatTracks = (DiskBase<<16)|(0x0006<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskReassignBlocks = (DiskBase<<16)|(0x0007<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskPerformance = (DiskBase<<16)|(0x0008<<2)|EMethod.Buffered|(0<<14),
DiskIsWritable = (DiskBase<<16)|(0x0009<<2)|EMethod.Buffered|(0<<14),
DiskLogging = (DiskBase<<16)|(0x000a<<2)|EMethod.Buffered|(0<<14),
DiskFormatTracksEx = (DiskBase<<16)|(0x000b<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskHistogramStructure = (DiskBase<<16)|(0x000c<<2)|EMethod.Buffered|(0<<14),
DiskHistogramData = (DiskBase<<16)|(0x000d<<2)|EMethod.Buffered|(0<<14),
DiskHistogramReset = (DiskBase<<16)|(0x000e<<2)|EMethod.Buffered|(0<<14),
DiskRequestStructure = (DiskBase<<16)|(0x000f<<2)|EMethod.Buffered|(0<<14),
DiskRequestData = (DiskBase<<16)|(0x0010<<2)|EMethod.Buffered|(0<<14),
DiskControllerNumber = (DiskBase<<16)|(0x0011<<2)|EMethod.Buffered|(0<<14),
DiskSmartGetVersion = (DiskBase<<16)|(0x0020<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskSmartSendDriveCommand = (DiskBase<<16)|(0x0021<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskSmartRcvDriveData = (DiskBase<<16)|(0x0022<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskUpdateDriveSize = (DiskBase<<16)|(0x0032<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskGrowPartition = (DiskBase<<16)|(0x0034<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskGetCacheInformation = (DiskBase<<16)|(0x0035<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskSetCacheInformation = (DiskBase<<16)|(0x0036<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskDeleteDriveLayout = (DiskBase<<16)|(0x0040<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskFormatDrive = (DiskBase<<16)|(0x00f3<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
DiskSenseDevice = (DiskBase<<16)|(0x00f8<<2)|EMethod.Buffered|(0<<14),
DiskCheckVerify = (DiskBase<<16)|(0x0200<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskMediaRemoval = (DiskBase<<16)|(0x0201<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskEjectMedia = (DiskBase<<16)|(0x0202<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskLoadMedia = (DiskBase<<16)|(0x0203<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskReserve = (DiskBase<<16)|(0x0204<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskRelease = (DiskBase<<16)|(0x0205<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskFindNewDevices = (DiskBase<<16)|(0x0206<<2)|EMethod.Buffered|(FileAccess.Read<<14),
DiskGetMediaTypes = (DiskBase<<16)|(0x0300<<2)|EMethod.Buffered|(0<<14),
// CHANGER
ChangerBase = EFileDevice.Changer,
ChangerGetParameters = (ChangerBase<<16)|(0x0000<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerGetStatus = (ChangerBase<<16)|(0x0001<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerGetProductData = (ChangerBase<<16)|(0x0002<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerSetAccess = (ChangerBase<<16)|(0x0004<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
ChangerGetElementStatus = (ChangerBase<<16)|(0x0005<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
ChangerInitializeElementStatus = (ChangerBase<<16)|(0x0006<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerSetPosition = (ChangerBase<<16)|(0x0007<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerExchangeMedium = (ChangerBase<<16)|(0x0008<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerMoveMedium = (ChangerBase<<16)|(0x0009<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerReinitializeTarget = (ChangerBase<<16)|(0x000A<<2)|EMethod.Buffered|(FileAccess.Read<<14),
ChangerQueryVolumeTags = (ChangerBase<<16)|(0x000B<<2)|EMethod.Buffered|((FileAccess.Read | FileAccess.Write)<<14),
// FILESYSTEM
FsctlRequestOplockLevel1 = (EFileDevice.FileSystem<<16) | (0<<2) | EMethod.Buffered | (0<<14),
FsctlRequestOplockLevel2 = (EFileDevice.FileSystem<<16) | (1<<2) | EMethod.Buffered | (0<<14),
FsctlRequestBatchOplock = (EFileDevice.FileSystem<<16) | (2<<2) | EMethod.Buffered | (0<<14),
FsctlOplockBreakAcknowledge = (EFileDevice.FileSystem<<16) | (3<<2) | EMethod.Buffered | (0<<14),
FsctlOpBatchAckClosePending = (EFileDevice.FileSystem<<16) | (4<<2) | EMethod.Buffered | (0<<14),
FsctlOplockBreakNotify = (EFileDevice.FileSystem<<16) | (5<<2) | EMethod.Buffered | (0<<14),
FsctlLockVolume = (EFileDevice.FileSystem<<16) | (6<<2) | EMethod.Buffered | (0<<14),
FsctlUnlockVolume = (EFileDevice.FileSystem<<16) | (7<<2) | EMethod.Buffered | (0<<14),
FsctlDismountVolume = (EFileDevice.FileSystem<<16) | (8<<2) | EMethod.Buffered | (0<<14),
FsctlIsVolumeMounted = (EFileDevice.FileSystem<<16) | (10<<2) | EMethod.Buffered | (0<<14),
FsctlIsPathnameValid = (EFileDevice.FileSystem<<16) | (11<<2) | EMethod.Buffered | (0<<14),
FsctlMarkVolumeDirty = (EFileDevice.FileSystem<<16) | (12<<2) | EMethod.Buffered | (0<<14),
FsctlQueryRetrievalPointers = (EFileDevice.FileSystem<<16) | (14<<2) | EMethod.Neither | (0<<14),
FsctlGetCompression = (EFileDevice.FileSystem<<16) | (15<<2) | EMethod.Buffered | (0<<14),
FsctlSetCompression = (EFileDevice.FileSystem<<16) | (16<<2) | EMethod.Buffered | ((FileAccess.Read | FileAccess.Write)<<14),
FsctlMarkAsSystemHive = (EFileDevice.FileSystem<<16) | (19<<2) | EMethod.Neither | (0<<14),
FsctlOplockBreakAckNo2 = (EFileDevice.FileSystem<<16) | (20<<2) | EMethod.Buffered | (0<<14),
FsctlInvalidateVolumes = (EFileDevice.FileSystem<<16) | (21<<2) | EMethod.Buffered | (0<<14),
FsctlQueryFatBpb = (EFileDevice.FileSystem<<16) | (22<<2) | EMethod.Buffered | (0<<14),
FsctlRequestFilterOplock = (EFileDevice.FileSystem<<16) | (23<<2) | EMethod.Buffered | (0<<14),
FsctlFileSystemGetStatistics = (EFileDevice.FileSystem<<16) | (24<<2) | EMethod.Buffered | (0<<14),
FsctlGetNtfsVolumeData = (EFileDevice.FileSystem<<16) | (25<<2) | EMethod.Buffered | (0<<14),
FsctlGetNtfsFileRecord = (EFileDevice.FileSystem<<16) | (26<<2) | EMethod.Buffered | (0<<14),
FsctlGetVolumeBitmap = (EFileDevice.FileSystem<<16) | (27<<2) | EMethod.Neither | (0<<14),
FsctlGetRetrievalPointers = (EFileDevice.FileSystem<<16) | (28<<2) | EMethod.Neither | (0<<14),
FsctlMoveFile = (EFileDevice.FileSystem<<16) | (29<<2) | EMethod.Buffered | (0<<14),
FsctlIsVolumeDirty = (EFileDevice.FileSystem<<16) | (30<<2) | EMethod.Buffered | (0<<14),
FsctlGetHfsInformation = (EFileDevice.FileSystem<<16) | (31<<2) | EMethod.Buffered | (0<<14),
FsctlAllowExtendedDasdIo = (EFileDevice.FileSystem<<16) | (32<<2) | EMethod.Neither | (0<<14),
FsctlReadPropertyData = (EFileDevice.FileSystem<<16) | (33<<2) | EMethod.Neither | (0<<14),
FsctlWritePropertyData = (EFileDevice.FileSystem<<16) | (34<<2) | EMethod.Neither | (0<<14),
FsctlFindFilesBySid = (EFileDevice.FileSystem<<16) | (35<<2) | EMethod.Neither | (0<<14),
FsctlDumpPropertyData = (EFileDevice.FileSystem<<16) | (37<<2) | EMethod.Neither | (0<<14),
FsctlSetObjectId = (EFileDevice.FileSystem<<16) | (38<<2) | EMethod.Buffered | (0<<14),
FsctlGetObjectId = (EFileDevice.FileSystem<<16) | (39<<2) | EMethod.Buffered | (0<<14),
FsctlDeleteObjectId = (EFileDevice.FileSystem<<16) | (40<<2) | EMethod.Buffered | (0<<14),
FsctlSetReparsePoint = (EFileDevice.FileSystem<<16) | (41<<2) | EMethod.Buffered | (0<<14),
FsctlGetReparsePoint = (EFileDevice.FileSystem<<16) | (42<<2) | EMethod.Buffered | (0<<14),
FsctlDeleteReparsePoint = (EFileDevice.FileSystem<<16) | (43<<2) | EMethod.Buffered | (0<<14),
FsctlEnumUsnData = (EFileDevice.FileSystem<<16) | (44<<2) | EMethod.Neither | (0<<14),
FsctlSecurityIdCheck = (EFileDevice.FileSystem<<16) | (45<<2) | EMethod.Neither | (FileAccess.Read<<14),
FsctlReadUsnJournal = (EFileDevice.FileSystem<<16) | (46<<2) | EMethod.Neither | (0<<14),
FsctlSetObjectIdExtended = (EFileDevice.FileSystem<<16) | (47<<2) | EMethod.Buffered | (0<<14),
FsctlCreateOrGetObjectId = (EFileDevice.FileSystem<<16) | (48<<2) | EMethod.Buffered | (0<<14),
FsctlSetSparse = (EFileDevice.FileSystem<<16) | (49<<2) | EMethod.Buffered | (0<<14),
FsctlSetZeroData = (EFileDevice.FileSystem<<16) | (50<<2) | EMethod.Buffered | (FileAccess.Write<<14),
FsctlQueryAllocatedRanges = (EFileDevice.FileSystem<<16) | (51<<2) | EMethod.Neither | (FileAccess.Read<<14),
FsctlEnableUpgrade = (EFileDevice.FileSystem<<16) | (52<<2) | EMethod.Buffered | (FileAccess.Write<<14),
FsctlSetEncryption = (EFileDevice.FileSystem<<16) | (53<<2) | EMethod.Neither | (0<<14),
FsctlEncryptionFsctlIo = (EFileDevice.FileSystem<<16) | (54<<2) | EMethod.Neither | (0<<14),
FsctlWriteRawEncrypted = (EFileDevice.FileSystem<<16) | (55<<2) | EMethod.Neither | (0<<14),
FsctlReadRawEncrypted = (EFileDevice.FileSystem<<16) | (56<<2) | EMethod.Neither | (0<<14),
FsctlCreateUsnJournal = (EFileDevice.FileSystem<<16) | (57<<2) | EMethod.Neither | (0<<14),
FsctlReadFileUsnData = (EFileDevice.FileSystem<<16) | (58<<2) | EMethod.Neither | (0<<14),
FsctlWriteUsnCloseRecord = (EFileDevice.FileSystem<<16) | (59<<2) | EMethod.Neither | (0<<14),
FsctlExtendVolume = (EFileDevice.FileSystem<<16) | (60<<2) | EMethod.Buffered | (0<<14),
FsctlQueryUsnJournal = (EFileDevice.FileSystem<<16) | (61<<2) | EMethod.Buffered | (0<<14),
FsctlDeleteUsnJournal = (EFileDevice.FileSystem<<16) | (62<<2) | EMethod.Buffered | (0<<14),
FsctlMarkHandle = (EFileDevice.FileSystem<<16) | (63<<2) | EMethod.Buffered | (0<<14),
FsctlSisCopyFile = (EFileDevice.FileSystem<<16) | (64<<2) | EMethod.Buffered | (0<<14),
FsctlSisLinkFiles = (EFileDevice.FileSystem<<16) | (65<<2) | EMethod.Buffered | ((FileAccess.Read | FileAccess.Write)<<14),
FsctlHsmMsg = (EFileDevice.FileSystem<<16) | (66<<2) | EMethod.Buffered | ((FileAccess.Read | FileAccess.Write)<<14),
FsctlNssControl = (EFileDevice.FileSystem<<16) | (67<<2) | EMethod.Buffered | (FileAccess.Write<<14),
FsctlHsmData = (EFileDevice.FileSystem<<16) | (68<<2) | EMethod.Neither | ((FileAccess.Read | FileAccess.Write)<<14),
FsctlRecallFile = (EFileDevice.FileSystem<<16) | (69<<2) | EMethod.Neither | (0<<14),
FsctlNssRcontrol = (EFileDevice.FileSystem<<16) | (70<<2) | EMethod.Buffered | (FileAccess.Read<<14),
// VIDEO
VideoQuerySupportedBrightness = (EFileDevice.Video << 16) | (0x0125 << 2) | EMethod.Buffered | (0 << 14),
VideoQueryDisplayBrightness = (EFileDevice.Video << 16) | (0x0126 << 2) | EMethod.Buffered | (0 << 14),
VideoSetDisplayBrightness = (EFileDevice.Video << 16) | (0x0127 << 2) | EMethod.Buffered | (0 << 14)
}
[DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
EIOControlCode dwIoControlCode,
IntPtr InBuffer,
int nInBufferSize,
IntPtr OutBuffer,
int nOutBufferSize,
ref int pBytesReturned,
[In] ref NativeOverlapped lpOverlapped
);
-
internal class DeviceIoOverlapped
{
private IntPtr mPtrOverlapped = IntPtr.Zero;
private int mFieldOffset_InternalLow = 0;
private int mFieldOffset_InternalHigh = 0;
private int mFieldOffset_OffsetLow = 0;
private int mFieldOffset_OffsetHigh = 0;
private int mFieldOffset_EventHandle = 0;
public DeviceIoOverlapped()
{
// Globally allocate the memory for the overlapped structure
mPtrOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (NativeOverlapped)));
// Find the structural starting positions in the NativeOverlapped structure.
mFieldOffset_InternalLow = Marshal.OffsetOf(typeof (NativeOverlapped), "InternalLow").ToInt32();
mFieldOffset_InternalHigh = Marshal.OffsetOf(typeof (NativeOverlapped), "InternalHigh").ToInt32();
mFieldOffset_OffsetLow = Marshal.OffsetOf(typeof (NativeOverlapped), "OffsetLow").ToInt32();
mFieldOffset_OffsetHigh = Marshal.OffsetOf(typeof (NativeOverlapped), "OffsetHigh").ToInt32();
mFieldOffset_EventHandle = Marshal.OffsetOf(typeof (NativeOverlapped), "EventHandle").ToInt32();
}
public IntPtr InternalLow
{
get { return Marshal.ReadIntPtr(mPtrOverlapped, mFieldOffset_InternalLow); }
set { Marshal.WriteIntPtr(mPtrOverlapped, mFieldOffset_InternalLow, value); }
}
public IntPtr InternalHigh
{
get { return Marshal.ReadIntPtr(mPtrOverlapped, mFieldOffset_InternalHigh); }
set { Marshal.WriteIntPtr(mPtrOverlapped, mFieldOffset_InternalHigh, value); }
}
public int OffsetLow
{
get { return Marshal.ReadInt32(mPtrOverlapped, mFieldOffset_OffsetLow); }
set { Marshal.WriteInt32(mPtrOverlapped, mFieldOffset_OffsetLow, value); }
}
public int OffsetHigh
{
get { return Marshal.ReadInt32(mPtrOverlapped, mFieldOffset_OffsetHigh); }
set { Marshal.WriteInt32(mPtrOverlapped, mFieldOffset_OffsetHigh, value); }
}
/// <summary>
/// The overlapped event wait hande.
/// </summary>
public IntPtr EventHandle
{
get { return Marshal.ReadIntPtr(mPtrOverlapped, mFieldOffset_EventHandle); }
set { Marshal.WriteIntPtr(mPtrOverlapped, mFieldOffset_EventHandle, value); }
}
/// <summary>
/// Pass this into the DeviceIoControl and GetOverlappedResult APIs
/// </summary>
public IntPtr GlobalOverlapped
{
get { return mPtrOverlapped; }
}
/// <summary>
/// Set the overlapped wait handle and clear out the rest of the structure.
/// </summary>
/// <param name="hEventOverlapped"></param>
public void ClearAndSetEvent(IntPtr hEventOverlapped)
{
EventHandle = hEventOverlapped;
InternalLow = IntPtr.Zero;
InternalHigh = IntPtr.Zero;
OffsetLow = 0;
OffsetHigh = 0;
}
// Clean up the globally allocated memory.
~DeviceIoOverlapped()
{
if (mPtrOverlapped != IntPtr.Zero)
{
Marshal.FreeHGlobal(mPtrOverlapped);
mPtrOverlapped = IntPtr.Zero;
}
}
}
Use the above class something like this:
DeviceIoOverlapped deviceIoOverlapped = new DeviceIoOverlapped();
ManualResetEvent hEvent = new ManualResetEvent(false);
deviceIoOverlapped.ClearAndSetEvent(hEvent.SafeWaitHandle.DangerousGetHandle());
int ret;
DeviceIoControl(hDevice, iCtlCode, inBuffer, inSize, outBuffer, outSize, out ret, deviceIoOverlapped.GlobalOverlapped)
The DeviceIoControl API must declare an IntPtr for the OVERLAPPED parameter. All other deviations are OK.