EjectUSB - version 1.6
by William Hedrick
modified by Framakey (confirmation dialog box)

Designed to be a simple utility to close all programs running from a specified drive or
folder and then attempt ejection if a drive was specified. Extended functionality includes
flushing the file cache, closing Explorer windows and removing registry entries and Recent
Document shortcuts referencing the specified drive or folder.

[00]======================================================================================

.: Contents

[01] Quick Start
[02] Settings
[03] Command Line Switches
[04] External Utility Support
[05] Frequently Asked Questions
[06] Change Log
[07] Acknowledgements
[08] Default INI File
[09] Disclaimer / License

[01]======================================================================================

.: Quick Start

EjectUSB reads its settings from EjectUSB.ini (in the same folder as EjectUSB.exe).
If EjectUSB.ini does not exist, EjectUSB will run with default settings. EjectUSB accepts
a drive letter or folder path as a command line argument (but doesn't require it).

Default settings are equivalent to all options being set to true and no inclusions or
exclusions. EjectUSB will detect the drive letter it was run from if no drive letter or
folder path is given via a command line argument.

EjectUSB will flush the file cache for the target location, close all programs running
from the target location, close any Explorer windows open to the target location, remove
Windows MUI and MRU entries and Recent Document shortcuts related to the target location,
and attempt to eject the specified drive (if the target location was a drive letter).

[02]======================================================================================

.: Settings

In EjectUSB.ini, the settings are presented thusly:
[Settings]
TimeToWait=
DoNotFlush=
DoNotClose=
NoPrograms=
NoGraceful=
NoExplorer=
DoNotClean=
NoRegistry=
NoFirewall=
NoShortcut=
DoNotSubst=
NoRedirect=
DoNotEject=
NoEjectAPI=
NoFakedMsg=

[Exclusions]

[Inclusions]

TimeToWait is the amount of time in seconds to wait for programs to close (and other
similar functions that wait for completion such as searching for visible windows).
Default value is 5.

DoNotFlush determines if EjectUSB will attempt to flush the file cache for the drive
specified (even in the presence of external ejection utilities).
A setting of 1 (or anything besides 0 or false) disables file cache flushing.
Default value is 0.

DoNotClose supersedes NoPrograms and NoExplorer meaning if it's set to 1 (or anything
besides 0 or false), no programs or explorer windows will be closed. If 0 (or false), then
NoPrograms, NoGraceful, and NoExplorer settings are used.
Default value is 0.

NoPrograms determines if EjectUSB will close programs running from the specified location.
A setting of 1 (or anything besides 0 or false) disables this functionality.
NoPrograms supersedes NoGraceful meaning if it's set to 1 (or anything besides 0 or
false), the NoGraceful setting won't be used (as it won't be necessary).
Default value is 0.

NoGraceful determines if EjectUSB will first attempt to "gracefully" (rather than
forcibly) close programs running from the specified location.
A setting of 1 (or anything besides 0 or false) disables this graceful closing.
Default value is 0.

NoExplorer determines if EjectUSB will close explorer windows currently viewing the
specified location.
A setting of 1 (or anything besides 0 or false) disables closing explorer windows.
Default value is 0.

DoNotClean supersedes NoRegistry, NoFirewall and NoShortcut meaning if it's set to 1 (or
anything besides 0 or false), no cleanup functions will be performed. If 0 (or false),
then NoRegistry, NoFirewall and NoShortcut settings are used.
Default value is 0.

NoRegistry determines if EjectUSB will remove references to the specified location from
Windows MUI and MRU registry entries.
A setting of 1 (or anything besides 0 or false) disables MUI and MRU registry cleanup.
Default value is 0.

NoFirewall determines if EjectUSB will remove firewall policy entries related to the
specified location from the registry.
A setting of 1 (or anything besides 0 or false) disables firewall policy cleanup.
Default value is 0.

NoShortcut determines if EjectUSB will remove recent document shortcuts related to the
specified location from the recent documents folder.
A setting of 1 (or anything besides 0 or false) disables recent document cleanup.
Default value is 0.

DoNotSubst supersedes NoRedirect meaning if it's set to 1 (or anything besides 0 or
false), the target location will not be tested to see if it's a Subst drive. If 0 (or
false), then EjectUSB will check if the drive is a Subst drive and ''unsubst'' the drive
before ejection.
Default value is 0.

NoRedirect determines if EjectUSB will change the target location to the source of the
Subst drive.
A setting of 1 (or anything besides 0 or false) disables target location redirection.
Default value is 0.

DoNotEject supersedes NoEjectAPI meaning if it's set to 1 (or anything besides 0 or
false), automatic drive ejection will not occur (even in the presence of Ejection Helper
Utilities). If 0 (or false), then EjectUSB will attempt to eject the drive specified.
Default value is 0.

NoEjectAPI determines if EjectUSB will use its internal API-based ejection function (if no
Ejection Helper Utilities are present).
A setting of 1 (or anything besides 0 or false) disables internal API-based ejection and
instead relies on manipulating the Safely Remove Hardware dialogs.
Default value is 0.

NoFakedMsg determines if EjectUSB will use its internal message balloon when ejection
succeeds, rather than triggering a delayed success message from Windows.
A setting of 0 (or false) makes EjectUSB create a message balloon on successful ejection.
Default value is 0.

Exclusions list part of a filename that won't be automatically closed. Registry wrappers
and portable launchers should be excluded. Entries should be numbered sequentially and
there should be realistically no limit to the number of entries.
Capitalization does not matter (NOT case sensitive).
There are no default entries; some example entries are:
0=Pocket
1=Portable
2=PStart.exe

Inclusions list part of a filename that will be automatically closed even if they're not
running from the removable drive. Entries should be numbered sequentially and there should
be realistically no limit to the number of entries.
Capitalization does not matter (NOT case sensitive).
There are no default entries; some example entries are:
0=.tmp\stdrt.exe
1=temp\aicon.exe

[03]======================================================================================

.: Command Line Switches

EjectUSB supports 6 command line arguments (which must be separated by spaces):
drive letter or folder path (Z:\, Z:\folder, "Z:\folder\sub folder")
/eject
/force
/ini
/nobat
/settings

If the path contains spaces it must be surrounded by quotation marks. A drive letter can
be specified as a single character (Z), or letter and colon (Z:), or a letter, colon and
backslash (Z:\). Capitalization does not matter (NOT case sensitive).

/eject ignores configuration file settings and attempts to eject the specified drive; this
bypasses all other functions (program closing, registry cleanup, etc.).

/force bypasses the validation check on the specified location. Its purpose is to utilize
EjectUSB's cleanup functions for a drive that isn't currently connected.

/ini followed by a filename explicitly specifies a settings file. Example: /ini config.ini

/nobat ignores the presence of a hybrid batch file. Its purpose is to prevent infinite
loops if EjectUSB is run from within the hybrid batch file.

/settings displays a settings interface window to make editing a settings file easier.

[04]======================================================================================

.: External Utility Support

EjectUSB can interface with various utilities to aid in drive ejection. These can be
referred to as Ejection Helper Utilities. The list below is in order of precedence.

If located in the same folder as EjectUSB (and named the same as in the following list)
the following utilities will be used to eject a drive instead of using EjectUSB's internal
ejection function:
- RemoveDrive.exe http://www.uwe-sieber.de/drivetools_e.html#RemoveDrive
- USB_Disk_Eject.exe http://quick.mixnmojo.com/software#usbdiskeject
- DevEject.exe http://www.withopf.com/tools/deveject/
- USBDeview.exe http://www.nirsoft.net/utils/usb_devices_view.html
- AutoStart.exe / AutoEject.exe http://xpt.nl/products-autostart

- EjectMedia.exe http://www.uwe-sieber.de/drivetools_e.html#EjectMedia
EjectMedia is also supported but is intended to be used with card readers, CDRom drives or
other devices with ejectable media. It takes precedence over the above utilities.

EjectUSB can use the following utilities to enumerate open file handles and close programs
with open file handles associated with the specified location. These can be referred to as
Handle Helper Utilities. The list below is in order of precedence.

If located in the same folder as EjectUSB (and named the same as in the following list)
the following utilities will be used to close open file handles:
- Unlocker.exe http://ccollomb.free.fr/unlocker/
  UnlockerDriver5.sys is also required. Both can be UniExtract'd from the installer.
- Handle.exe http://www.microsoft.com/technet/sysinternals/ProcessesAndThreads/Handle.mspx
  Version 3.20 or lower of Handle is required for compatibility with Win9x.

EjectUSB can use the following utilities to aid in file cache flushing. These can be
referred to as File Cache Helper Utilities. The list below is in order of precedence.

If located in the same folder as EjectUSB (and named the same as in the following list)
the following utilities will be used to flush the file cache instead of using EjectUSB's
internal file cache flushing function:
- Sync.exe http://www.microsoft.com/technet/sysinternals/FileAndDisk/Sync.mspx

[05]======================================================================================

.: Frequently Asked Questions

- Why is my drive failing to eject?

There are many things that can prevent a removable drive from getting permission from
Windows to safely eject. The usual cause, however, is that a file that is located on the
removable drive is either running (if it's a program) or is in use by a program.

- Is it safe to unplug my drive even if Windows says it's still in use?

The short answer is: usually. Windows isn't telling you it isn't safe to be mean or
annoying, but to prevent data loss or damage to your drive. The entire purpose of EjectUSB
is to get Windows to turn off your drive so it's 100% safe to remove without fear of
losing a file or causing damage and to accomplish this as quickly as possible.

- EjectUSB is failing to eject my drive, what can I do?

If you have administrator privileges on the computer where EjectUSB is failing to eject a
drive, one of the Handle Helper Utilities (listed in the previous section) may be able to
solve the problem.

Try increasing the TimeToWait value in the configuration INI file. While 5 (seconds) is
default and has been adequate in all testing environments, a larger value might give
Windows enough time to allow for a proper ejection.

As an alternative, download one of the Ejection Helper Utilities (listed in the previous
section) and place the executable in the same folder as EjectUSB.

- Can I speed up EjectUSB so it ejects a drive more quickly?

You could disable graceful closing and the cleanup routines to save a few seconds.

Setting NoFakedMsg to 1 (or anything besides 0 or false) can delay the ejection success
message by a significant amount of time.

Decreasing the TimeToWait value may speed things up, but could cause ejection to fail.

- My drive hasn't ejected and there's an EjectUSB icon in my system tray, what's wrong?

EjectUSB is repeatedly trying to eject the drive but is failing; click the EjectUSB tray
icon and choose Exit, make sure the drive is not in use, and then try again.

[06]======================================================================================

.: Change Log

Version 1.6
- Bug fix: EjectUSB no longer triggers file access errors on WinXP when run from read-only
  media when trying to load its hourglass tray icon.
- Bug fix: Sysinternals registry keys are no longer erroneously deleted.

Version 1.5
- Bug fix: EjectUSB's ejection success message will more reliably appear on Vista.
- Bug fix: EjectUSB's ejection success message will only disappear when the ejected drive
  is unplugged instead of disappearing when any USB device is unplugged.
- Bug fix: EjectUSB will no longer display an error if WMI functions fail.
- Improvement: EjectUSB's ejection success message now displays the ejected drive's name.
- Addition: Added /ini command line argument to allow a settings file to be specified.
- Addition: Added /settings command line argument to display a settings interface window.
- Addition: Included Settings.bat with the download to make adjusting settings easier.
- Change: Modified the manifest information.

Version 1.4
- Bug fix: Graceful program closing no longer only targets programs with a visible window.
- Bug fix: Flushing file buffers can no longer cause ejection to fail.
- Improvement: Dead tray icon cleanup is more resilient and slightly faster.
- Improvement: EjectUSB can now generate its own ejection success message. This will make
  ejection seem much faster on most computers.
- Addition: Added NoFakedMsg setting to the configuration file format.

Version 1.3
- Bug fix: Program closing on Win9x works again (was broken in 1.2).
- Bug fix: Fixed issues on Win9x when running EjectUSB from a drive's root folder.
- Improvement: Implemented hybrid batch scripting. This provides theorhetical support for
  TrueCrypt and combination flash card / flash drives as well as conditional operations.
- Improvement: EjectUSB can now interface with EjectMedia.exe to eject flash cards / CDs.
- Improvement: Implemented support for Subst.
- Addition: Added DoNotSubst and NoRedirect settings to the configuration file format.
- Addition: Added /nobat command line argument to disable use of the hybrid batch file (if
  present). Meant to be used within the hybrid batch file if starting another instance of
  EjectUSB to prevent infinite loops.

Version 1.2
- Bug fix: Improved handling of relative paths (\ and ..).
- Improvement: Implemented API-based ejection.
- Improvement: Implemented file cache flushing. Requires admin privileges.
- Improvement: EjectUSB can now interface with Sync (from Sysinternals) to flush the file
  cache (instead of using its own internal file cache flushing function). Requires admin
  privileges.
- Improvement: Improved command line argument parsing; drive letter or folder path no
  longer are required at all and no longer must be the first command line argument.
- Improvement: Efficiency improvements related to DLL calls.
- Addition: Added DoNotFlush and NoEjectAPI settings to the configuration file format.
- Change: RemoveDrive.exe is called with the -L switch to loop until successful ejection.
  This can be aborted by closing the RemoveDrive.exe console window.
- Change: DevEject.exe is now launched hidden.
- Change: Added current version number to EjectUSB.exe version info.

Version 1.1
- Bug fix: Improved ejection capability via EjectUSB's own internal ejection routine.
- Bug fix: Improved command line argument and input parsing for handle.exe; there were
  some formatting differences between the output on Win9x and WinXP.
- Bug fix: TimeToWait is now a maximum per ''phase'' rather than per program; in rare
  cases EjectUSB could wait for multiple minutes on closing programs with the default
  TimeToWait value of 5 (seconds).
- Bug fix: Cleaning up dead tray icons was triggered by faulty criteria; in simple terms,
  dead tray icon cleanup was occuring when it didn't need to (wasting up to 1 second).
- Improvement: Minor efficiency improvements related to the previous two changes.
- Improvement: EjectUSB can now interface with Unlocker to close open file handles; simply
  UniExtract the Unlocker installer and put Unlocker.exe and UnlockerDriver5.sys in the
  same folder as EjectUSB. Unlocker requires admin privileges and doesn't work on Win9x.
- Improvement: Added a FAQ section to the documentation.
- Change: Slight change to the EjectUSB logo.
- Change: Separated the source code into its own ZIP file. Source code for EjectUSB will
  always be released with each version of EjectUSB.

Version 1.0
- Initial release.

[07]======================================================================================

.: Acknowledgements
ashghost - For providing registry exports to help me build the cleanup routines.
MiDoJo - For providing registry exports and patiently helping me test Vista compatibility.
Steen - For helping track down a critical Win9x compatibility problem.
guinness - For providing TrueCrypt support testing and bug testing.
larry - For locating a registry cleanup flaw (related to Sync and Handle).

[08]======================================================================================

.: Default INI File

[Settings]
TimeToWait=5
DoNotFlush=0
DoNotClose=0
NoPrograms=0
NoGraceful=0
NoExplorer=0
DoNotClean=0
NoRegistry=0
NoFirewall=0
NoShortcut=0
DoNotSubst=0
NoRedirect=0
DoNotEject=0
NoEjectAPI=0
NoFakedMsg=0

[Exclusions]
0=Pocket
1=Portable
2=PStart.exe

[Inclusions]
0=.tmp\stdrt.exe

[09]======================================================================================

.: Disclaimer / License

Your use of EjectUSB is at your own risk and no guarantee is given as to the operation or
performance of said program. You may reverse engineer and/or use the source code for
EjectUSB so long as credit is given to the original author (William Hedrick) for any
derivative works. The EjectUSB logo may not be used for any purposes except as an icon
to represent EjectUSB.
