Safely Remove Hardware

To Safely Remove Hardware in Windows, normally the user will click on the appropriate system tray icon. Here are some alternatives to that method.

From the Command Line

When executed at a command line, the following command causes the Safely Remove Hardware dialog to appear.

RunDll32.exe shell32.dll,Control_RunDLL hotplug.dll

From VB6

The following EjectDeviceByDriveLetter() function will safely remove the device as indicated by the specified drive letter.

Private Declare Function GetVersion Lib "kernel32" () As Long

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As _
String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As _
Long) As Long

Private Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal _
dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, _
ByVal nOutBufferSize As Long, lpBytesReturned As Long, lpOverlapped As Any) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const OPEN_EXISTING = 3
Private Const FILE_FLAG_DELETE_ON_CLOSE = 67108864
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const IOCTL_STORAGE_EJECT_MEDIA = 2967560
Private Const VWIN32_DIOC_DOS_IOCTL = 1
  reg_EBX As Long
  reg_EDX As Long
  reg_ECX As Long
  reg_EAX As Long
  reg_EDI As Long
  reg_ESI As Long
  reg_Flags As Long
End Type
Private Sub EjectDeviceByDriveLetter(EjectDrive as String)

    Dim hDrive As Long, DummyReturnedBytes As Long
    Dim EjectDrive As String, DriveLetterAndColon As String
    Dim RawStuff As DIOC_REGISTERS
    DriveLetterAndColon = UCase$(Left$(EjectDrive, 1) & ":") 

    '-- Handle Windows NT/2000 --------------------------------------------------------------------
    If GetVersion >= 0 Then 

        hDrive = CreateFile("\\.\" & DriveLetterAndColon, GENERIC_READ Or GENERIC_WRITE, 0, ByVal _
                    0, OPEN_EXISTING, 0, 0)
        If hDrive <> INVALID_HANDLE_VALUE Then
            ' Eject media 
            Call DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, DummyReturnedBytes, ByVal 0)
            ' Clean Up 
            Call CloseHandle(hDrive)  
        End If
    '-- Handle Win9x/ME ---------------------------------------------------------------------------
        hDrive = CreateFile("\\.\VWIN32", 0, 0, ByVal 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0)
        If hDrive <> INVALID_HANDLE_VALUE Then
            '-- Setup raw registers ---------------------------------------------------------------
            'to use Interrupt 21h Function 440Dh Minor Code 49h
            'The function to use
            RawStuff.reg_EAX = &H440D
            'The drive to do it on 
            RawStuff.reg_EBX = Asc(DriveLetterAndColon) - Asc("A") + 1
            'The minor code of the function in the low byte of the low word and the device 
            'category of 8 in the high byte of the low word 
            RawStuff.reg_ECX = &H49 Or &H800     
            '-- Eject media and Clean Up ----------------------------------------------------------
            Call DeviceIoControl(hDrive, VWIN32_DIOC_DOS_IOCTL, RawStuff, LenB(RawStuff), _
                        RawStuff, LenB(RawStuff), DummyReturnedBytes, ByVal 0)
            Call CloseHandle(hDrive)  'Clean up after ourselves
        End If
    End If

End Sub