Need help importing IOCTL_STORAGE_EJECTION_CONTROL to C#
-
Thursday, August 27, 2009 11:55 AM
Anyone know how to do this? The problem I wish to solve is to prevent the end user from manually opening their CD drive whilsts I am verifying the disk using a third party program.
So far I've figured that I need to import the DeviceIoControl function and use that with IOCTL_STORAGE_EJECTION_CONTROL
I've read a couple of threads on the topic now, but I cannot find a good C# example and I find that porting C++ to C# is really hard, espically when you don't know any C++. I've got this far with the code.
/// <summary>Locks the disk drive in someway, somehow</summary> [return: MarshalAs(UnmanagedType.Bool)] [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] int dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); public static SafeFileHandle CreateFileR(string device) { string str = device.EndsWith(@"\") ? device.Substring(0, device.Length - 1) : device; return new SafeFileHandle(CreateFile(@"\\.\" + device, WinntConst.GENERIC_READ, WinntConst.FILE_SHARE_READ, IntPtr.Zero, WinntConst.OPEN_EXISTING, WinntConst.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true); } public void LockDrive() { SafeFileHandle _hdev = CreateFileR(destVolume); if (!(_hdev.IsClosed | _hdev.IsInvalid)) { result = DeviceIoControl(_hdev, IOCTL_STORAGE_EJECTION_CONTROL, (IntPtr.Zero)true, 0, buffer, sizeof(int), out bytesReturned, IntPtr.Zero); } }
But now I'm just even more confused.
I need to figure out what "WinntConst" is and how to import it. Plus I need to import DWORD, LPVOID, LPDWORD and LPOVERLAPPED but I don't know which API to find these in. Could anyone help? Will this even do what I want it to do?
Do Crabs Think We Walk Sideways??
All Replies
-
Thursday, August 27, 2009 12:23 PMModerator
Yeah, you're not close. Use pinvoke.net for declarations.
Hans Passant.- Marked As Answer by David M MortonModerator Saturday, August 29, 2009 6:12 PM
-
Thursday, August 27, 2009 2:15 PMah brilliant, that website is amazing and has sorted me out. All I need now is to call IOCTL_STORAGE_EJECTION_CONTROL and PREVENT_MEDIA_REMOVAL.
I know it has something to do with Winioctl.h, but I'm not entirely sure on how to go about implementing it. Should only take an afternoon to figure out methinks.
Do Crabs Think We Walk Sideways?? -
Thursday, September 24, 2009 2:57 PMDid you ever figure it out? I am trying to do the same thing ..
-
Thursday, September 24, 2009 3:47 PM
Yes I have a full solution, with a little help from CodeProjects. I voiced the question over there and not only did I get a good response and the Dll Imports but a very kind gentleman named DaveyM69 actually went and did the work for me. Like him, I don't agree with handouts, but because he's put in the effort I believe it'd be beneficial for all that this to be useable by anyone who seeks it. I hope he agrees ^_^
Here's the link to the thread: http://www.codeproject.com/Messages/3176273/Re-Preventing-the-user-from-Ejecting-the-CD-during.aspx
And here is the class in full (It's static btw). It's by DaveyM69 of CodeProjects so I don't and won't take any credit for this code. All I've done is commented bits of it and included both IOCTL_STORAGE_MEDIA_REMOVAL and IOCTL_STORAGE_EJECTION_CONTROL variables, but that isn't much.
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Threading; namespace DriveControl { /// <summary>This class is dedicated to locking and unlocking the CD ejection. /// Here we are importing COM classes relating to DeviceIOControl and using it /// to set Media removal to false. /// NOTE: At time of writing there are complications implementing this class</summary> public static class CDLockDrive { /// <summary>Main method of the class, LockMedia locks and unlocks a drive</summary> public static bool LockMedia(string driveLetter, bool lockDrive) { bool result = false; string fullDrivePath = string.Format(@"\\.\{0}", driveLetter); SECURITY_ATTRIBUTES securityAttributes = new SECURITY_ATTRIBUTES(); IntPtr hDrive = CreateFile( // CreateFile gets a drive handle fullDrivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, ref securityAttributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero); if (hDrive != INVALID_HANDLE_VALUE) { IntPtr outBuffer; int bytesReturned; NativeOverlapped overlapped = new NativeOverlapped(); result = DeviceIoControl( hDrive, IOCTL_STORAGE_MEDIA_REMOVAL, // Inputs media removal to DeiceIOControl ref lockDrive, // Bool, true to lock, false to unlock 1, out outBuffer, 0, out bytesReturned, ref overlapped); CloseHandle(hDrive); } return result; // Was the locking of the disk tray successful? } // These values are gather from enumerations for the COM classes private const uint GENERIC_READ = 0x80000000; private const int FILE_SHARE_READ = 0x00000001; private const int FILE_SHARE_WRITE = 0x00000002; private const int OPEN_EXISTING = 3; private const int FILE_ATTRIBUTE_NORMAL = 0x80; private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); // These two constants allow DeviceIOControl to lock and unlock disk trays private const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x2D4804; private const int IOCTL_STORAGE_EJECTION_CONTROL = 0x2D0940; // Imports the DeviceIOControl method from Kernel32 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool DeviceIoControl( IntPtr hDevice, int dwIoControlCode, ref bool lpInBuffer, int nInBufferSize, out IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, ref NativeOverlapped lpOverlapped); // Imports the CreateFile method from Kernel32 [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, int dwShareMode, ref SECURITY_ATTRIBUTES lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); // Imports the Close Handle method from Kernel32 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle( IntPtr hObject); [StructLayout(LayoutKind.Sequential)] private struct SECURITY_ATTRIBUTES { int nLength; IntPtr lpSecurityDescriptor; bool bInheritHandle; } } }To use:
Import this into your project and call the static function: LockMedia(string driveLetter, bool lockDrive)
Where driveLetter is the letter of the drive you want to lock :)
and lockDrive is true if you want to lock and false if you want to unlock.
Don't forget, the drive will remained locked until you release every lock you put on. So if you lock it 3 times, you have to unlock it 3 times.
http://msdn.microsoft.com/en-us/library/ms804575.aspx
Note: I was attempting to use this during the execution of a windows service/process. However, whilst the service/process was running it did not lock or unlock. I'm not sure why, but it seems to work on it's own.
I hope this helps
~Tyramon./
Do Crabs Think We Walk Sideways??- Proposed As Answer by Amolpbhavsar Wednesday, March 07, 2012 12:35 PM
-
Wednesday, March 07, 2012 1:23 PM
Thanks Tyranin,
this is really good example found by you and becoming helpful for me. It is also working properly on XP, Vista and Windows7 also properly.
Thanks for the code again
- Edited by Amolpbhavsar Wednesday, March 07, 2012 1:24 PM

