[comment {-*- tcl -*- doctools manpage}]
[manpage_begin "Device management" n ""]
[copyright "2008-2014 Ashok P. Nadkarni"]
[moddesc "Device management"]
[titledesc "Commands related to devices and device interfaces"]
[require twapi_device]
[description]
[para]

This package provides procedures related to device information and
management in Windows operating systems.


[section "Media control"]
The commands [uri #eject_media [cmd eject_media]], 
[uri #load_media [cmd load_media]] and
[uri #lock_media [cmd lock_media]] and
[uri #unlock_media [cmd unlock_media]] provide control
over removable devices and media.

[section "Device notifications"]

Device notifications are generated by Windows to inform applications
about changes in device configurations as well as related events. 
For example, notifications can be used by an application to learn about
media change in CD-ROM drives, plugging in of a USB device, mounting
a remote share and so on. These notifications allow applications to
save any changes and release resources as appropriate.

[para] Notifications are also used by the system
to inform applications about pending changes giving them the chance
to cancel them.

[para] TWAPI delivers device notifications through callback scripts
registered by the application through the 
[uri #start_device_notifier [cmd start_device_notifier]] command.
Applications must specify the
device or device interface class for which they wish to receive
notifications and the corresponding script to be invoked to receive
them.

[section "Physical disks"]

The [uri #find_physical_disks [cmd find_physical_disks]] command
returns the list of physical disks installed in the system.
The [uri #get_physical_disk_info [cmd get_physical_disk_info]]
command can then be used to retrieve detailed information about the
physical disk.

[section "Device management"]

The [uri #device_ioctl [cmd device_ioctl]] command provides thin
wrapper around the DeviceIoControl Win32 function. This allows for
device specific control commands to be issued to devices. You will
need to refer to the Windows SDK documentation for specifics of
the ioctls supported by various devices.

The [uri #devinfoset [cmd devinfoset]] command returns a handle
to a device information set that contains device elements corresponding
to devices in the system. A device element or the entire set
can then be retrieved with [uri #devinfoset_element [cmd devinfoset_element]]
and [uri #devinfoset_elements [cmd devinfoset_elements]] respectively.
The device instance identifiers for the devices in the set 
are available through
[uri #devinfoset_instance_ids [cmd devinfoset_instance_ids]].
To get properties of a device, such as its description, bus number etc., use
[uri #devinfoset_element_registry_property [cmd devinfoset_element_registry_property]].


The command [uri #rescan_devices [cmd rescan_devices]] forces
the device manager to rescan the system for all devices.


[section Commands]
[list_begin definitions]

[call [cmd device_ioctl] [arg DEVICEHANDLE] [arg IOCTLCODE] [opt "[cmd -outputcount] [arg BUFSIZE]"]]
This is a thin wrapper around the Win32 [cmd DeviceIoControl] function.
Primary role of the wrapper is to do
automatic output buffer management for the caller. [arg DEVICEHANDLE],
usually obtained through
[uri base.html#create_file [cmd create_file]],
is a handle to the device of interest. [arg IOCTLCODE] is the IOCTL code
to be sent to the device. The [cmd -outputcount] option should be specified
if the call is expected to return data. [arg BUFSIZE] should be the size
of the output buffer expected by the call. The command will then return
the result as a Tcl binary value that should in general be
parsed with the Tcl [cmd "binary scan"] command.

[call [cmd device_element] [arg FIELD] [arg DEVICE_ELEMENT]]
Returns the specified field from a device element structure. [arg FIELD]
must be [const class_guid] or [const device_instance]. 
The former is the GUID of the device's setup class. The latter is an
opaque handle to the device's [const devnode].
[arg DEVICE_ELEMENT]
is an opaque structure containing a device element as returned by
the [uri #devinfoset_element [cmd devinfoset_element]] or
[uri #devinfoset_elements [cmd devinfoset_elements]] calls.

[call [cmd devinfoset] [arg options]]
Returns a handle to a device information set containing device elements.
The returned handle must be closed by calling 
[uri #devinfoset_close [cmd devinfoset_close]].

The included elements depend on the options specified. Without any options,
all device elements are included. Otherwise the elements are restricted
to those matching one or more of the options in the table below.

[list_begin opt]
[opt_def [cmd -classtype] [const setup|interface]]
Specifies whether the GUID specified by the [arg GUID] option is
that of a device setup class (default) or a device interface class.
[opt_def [cmd -currentprofileonly] [arg BOOLEAN]]
If specified as [const true], only devices present in the current
hardware profile are included in the set. Default is [const false].
[opt_def [cmd -guid] [arg GUID]]
The GUID for a device setup class or a device interface class depending
on the [cmd -classtype] option. Only devices belonging to the class
with that GUID are returned. If unspecified or the empty string, devices
from all classes are included in the information set.
[opt_def [cmd -pnpenumerator] [arg PNPENUMERATOR]]
If specified, only devices for that PnP enumerator are returned.
[arg PNPENUMERATOR] may be the GUID of the enumerator or it symbolic
name such as [const USB], [const PCI], [const PCMCIA], [const SCSI] etc.
This option can only be used if the [cmd -classtype] option is [const setup].
[opt_def [cmd -presentonly] [arg BOOLEAN]]
If specified as [const true], only devices currently present in the system
are included in the set. Default is [const false].
[list_end]

[call [cmd devinfoset_close] [arg HDEVINFOSET]]
Closes a handle to device information set as returned by
[uri #devinfoset [cmd devinfoset]].

[call [cmd devinfoset_element] [arg HDEVINFOSET] [arg INSTANCEID]]
Returns the device element within a device information
set corresponding to the device instance identifier [arg INSTANCEID].
[arg HDEVINFOSET] is a handle to a device information set as
returned by [uri #devinfoset [cmd devinfoset]]. Use
[uri #device_element [cmd device_element]] to extract each field
in the element.

[call [cmd devinfoset_element_registry_property] [arg HDEVINFOSET] [arg DEVICELEM] [arg PROPERTY]]
Returns the value of a registry property for a device element in a
device information set.
[arg HDEVINFOSET] is a handle to a device information set as
returned by [uri #devinfoset [cmd devinfoset]].
[arg DEVICEELEMENT]
is an opaque structure containing a device element as returned by
the [uri #devinfoset_element [cmd devinfoset_element]] or
[uri #devinfoset_elements [cmd devinfoset_elements]] calls.
[arg PROPERTY] is one of the following:
[const devicedesc], [const hardwareid], [const compatibleids], 
[const service], [const class], [const classguid], [const driver], 
[const configflags], [const mfg], [const friendlyname],
[const location_information], [const physical_device_object_name], 
[const capabilities],
[const ui_number], [const upperfilters], [const lowerfilters],
[const bustypeguid], [const legacybustype], [const busnumber], 
[const enumerator_name], [const security],
[const security_sds], [const devtype], [const exclusive], 
[const characteristics], [const address],
[const ui_number_desc_format], [const device_power_data],
[const removal_policy], [const removal_policy_hw_default], 
[const removal_policy_override],
[const install_state], [const location_paths], or [const base_containerid].
Refer to the documentation of [cmd SetupDiGetDeviceRegistryProperty]
in the Windows SDK for the meaning of these properties.

Note that not all properties will exist for a device and the command
will raise an error if an attempt is made to retrieve a non-existing
property.

[call [cmd devinfoset_elements] [arg HDEVINFOSET]]
Returns a list containing the device elements within a device information
set. [arg HDEVINFOSET] is a handle to a device information set as
returned by [uri #devinfoset [cmd devinfoset]]. Use
[uri #device_element [cmd device_element]] to extract each field
in an element.

[call [cmd devinfoset_instance_ids] [arg HDEVINFOSET]]
Returns a list containing the device instance identifiers for all
devices in a device information set.
[arg HDEVINFOSET] is a handle to a device information set as
returned by [uri #devinfoset [cmd devinfoset]].

[call [cmd eject] [arg DEVICE]]
Alias for [uri #eject_media [cmd eject_media]].

[call [cmd eject_media] [arg DEVICE]]
Ejects a removable device, such as a CD-ROM or pen drive.
[arg DEVICE] should be of the form [arg X:], [arg X:\\], [arg X:/]
where [arg X] is a drive letter, or a physical disk path as returned
by the [uri #find_physical_disks [cmd find_physical_disks]] command,
or [const cdrom], in which case the first CD-ROM in the device list
is ejected.

[call [cmd find_physical_disks]]
Returns the list of physical disks in the system. The returned paths
can be passed to [cmd CreateFile] or
[uri device.html#create_file [cmd create_file]] to get a handle
to the raw physical disk.

[call [cmd get_physical_disk_info] [arg DISK] [opt [arg options]]]

Returns information about a physical disk. [arg DISK] is a device path
to the physical disk in the format returned by
[uri #find_physical_disks [cmd find_physical_disks]].
The command returns a keyed list with fields depending on the passed
options:

[list_begin opt]
[opt_def [cmd -all]] Returns all fields.
[opt_def [cmd -geometry]] Returns the geometry of the disk. The value is
itself a keyed list with the fields [cmd -cylinders], [cmd -mediatype],
[cmd -trackspercylinder], [cmd -sectorspertrack] and [cmd -bytespersector].
[opt_def [cmd -layout]] Returns the layout of the disk in terms of
how it is partitioned. The returned value is a keyed list with the fields
depending on how the disk is partitioned. See below for a discussion.
[list_end]

[nl]
The partitioning of a disk can take several forms and the information
returned by the [cmd -layout] differs in each case. The following is a brief
summary that assumes familiarity with disk formats. See the
[uri http://msdn.microsoft.com/en-us/library/aa972908.aspx "Windows DDK"]
documentation for details.

[nl]
On Windows XP and newer operating systems, the [cmd -layout] field value
is a keyed list with the fields, [cmd -partitioncount],
[cmd -partitionstyle] and [cmd -partitions]. If the [cmd -partitionstyle]
field is [const mbr], an additional field [cmd -signature] is present. If
the [cmd -partitionstyle] is [const gpt], three additional fields
[cmd -startingusableoffset], [cmd -usablelength] and [cmd -maxpartitioncount].
Other possible value of [cmd -partitionstyle] are
[const raw] or [const unknown] in which case there are no additional fields.
The [cmd -partitions] field is a list each element of which
is itself a keyed list containing information about each partition. Note
that the number of elements of the [cmd -partitions] list may not match
the value of the [cmd -partitioncount] field in case information for
some partitions cannot be retrieved. Every element of the [cmd -partitions]
field will have the fields [cmd -partitionstyle], [cmd -startingoffset],
[cmd -partitionlength], [cmd -partitionnumber] and [cmd -rewritepartition].
In addition, if [cmd -partitionstyle] is [const mbr], the element will
also have the fields
[cmd -hiddensectors],
[cmd -partitiontype], [cmd -bootindicator] and
[cmd -recognizedpartition]. If [cmd -partitionstyle] is [const gpt],
it will have the fields [cmd -partitiontype], [cmd -partitionif],
[cmd -attributes] and [cmd -name]. Partition styles [const raw] and
[const unknown] have no additional fields.

[call [cmd load_media] [arg DEVICE]]
Load removable media such as a CD or DVD.
[arg DEVICE] should be of the form [arg X:], [arg X:\\], [arg X:/]
where [arg X] is a drive letter, or a physical disk path as returned
by the [uri #find_physical_disks [cmd find_physical_disks]] command,
or [const cdrom], in which case the first CD-ROM in the device list
is loaded.

[call [cmd lock_media] [arg DEVICE]]
Locks the media in a device with removable media such as a CD-ROM.
On devices that support this function (not all do), locking the
media will prevent the media from being ejected. The media can be
unlocked with [uri #unlock_media [cmd unlock_media]].
[arg DEVICE] should be of the form [arg X:], [arg X:\\], [arg X:/]
where [arg X] is a drive letter, or a physical disk path as returned
by the [uri #find_physical_disks [cmd find_physical_disks]] command,
or [const cdrom], in which case the media in the
first CD-ROM in the device list is locked.

[call [cmd rescan_devices]]
Asks the device manager to rescan the system for all devices.

[call [cmd start_device_notifier] [arg SCRIPT] [opt "[cmd -deviceinterface] [arg DEVICEINTERFACE]"] [opt "[cmd -handle] [arg DEVICEHANDLE]"]]

Registers [arg SCRIPT] to be invoked when the events are generated from
a specified device class or device.
[nl]
The command creates a new notifier and returns its identifier.
When no longer interested in the specified changes, the
returned identifier should be passed to
[uri \#stop_device_notifier [cmd stop_device_notifier]] to stop the
notifications and release associated resources.

[nl]
If no additional
options were specified to the command, or if the [cmd -deviceinterface]
option was specified with [arg DEVICEINTERFACE] as an empty string, all device
interfaces are monitored. If [arg DEVICEINTERFACE] is one of the keywords
[const port] or [const volume], then all ports and all volumes respectively are
monitored. Otherwise, [arg DEVICEINTERFACE] must be the GUID for a
particular device interface class, and only that interface class is monitored.
Refer to the Windows SDK for a list of GUIDs for various device interface
classes.

[nl]
If the [cmd -handle] option is specified, [arg DEVICEHANDLE] must be
a handle to a resource on the device obtained through either
[uri file.html#create_file [cmd create_file]] or 
[uri base.html#get_tcl_channel_handle [cmd get_tcl_channel_handle]]. In
this case, only event notifications from that particular device are
passed to the callback script.

[nl]
At most one of the options [cmd -deviceinterface] and [cmd -handle] can be
specified.

[nl] The callback [arg SCRIPT] is invoked with additional arguments.
The first argument is the id of the notifier that was returned by this
command.  The second argument is the event notification type and may
be followed by additional arguments specific to the type.

[nl] For compatibility with future releases, the callback script should
ignore notification types not listed below. For the same reason, it should
also ignore any additional arguments or unexpected values for listed arguments.

[nl] Certain event types require the callback script to return a value. These
are noted below.

[nl] The notification type and the corresponding arguments are shown
in the table below.  The symbols match exactly the DBT_* symbols
defined in the Windows SDK except for the character case and prefix.
For example, [const devicearrival] corresponds to [const DBT_DEVICEARRIVAL].
More detail about each event can be obtained by
looking at the SDK documentation for the corresponding symbol.

[list_begin opt]
[opt_def [const configchangecanceled]]
A request to change the current dock/undock device configuration was canceled.
No additional arguments are present.

[opt_def [const configchanged]]
The current device configuration has changed due to docking or undocking.
No additional arguments are present.

[opt_def [const customevent]]
A custom event defined by a driver. An additional argument [emph may] be
present if the notifier was created with a [cmd -devicehandle] option. This
provides more detail on the event and has one of the following values:
[const io_volume_change],
[const io_volume_dismount],
[const io_volume_dismount_failed],
[const io_volume_mount],
[const io_volume_lock],
[const io_volume_lock_failed],
[const io_volume_unlock],
[const io_volume_name_change],
[const io_volume_physical_configuration_change],
[const io_volume_device_interface],
[const io_media_arrival],
[const io_media_removal],
[const io_device_becoming_ready],
[const io_device_external_request],
[const io_media_eject_request],
[const io_drive_requires_cleaning],
[const io_tape_erase],
[const io_disk_layout_change]. Refer to the Windows SDK and DDK for
more information on these.

[opt_def [const devicearrival]]
A new device or media has become available.
The first additional argument is one of [const deviceinterface],
[const handle], [const port] or [const volume] depending on source
of the notification.

[nl] If this first argument in [const deviceinterface],
(ie. device interfaces are being monitored ([arg DEVICEINTERFACE]
is unspecified, an empty string, or a device interface GUID), it is
followed by the device interface class GUID for the new device
interface, and the device interface class name.

[nl] If the value is [const handle], two additional arguments may be present
containing the internal device and notification handles. These should be
treated as opaque.

[nl] If the value is [const port], one additional argument, the name of
the port, may be present.

[nl] If the value is [const volume], the first additional argument is
a list of drive
letters corresponding to the new detected volumes (note there may be more
than one). This is followed by a list of attributes. If the list
includes [const mediachange], it indicates that new media was inserted
(e.g. a CD-ROM); otherwise, it indicates a new physical device (e.g. a
USB pen drive). If the list includes [const networkvolume], it indicates
the new volume is accessed over the network.

[opt_def [const devicequeryremove]] Request permission to remove a device.
The application can deny the request by returning the string [const deny].
Any other value will be treated as an allow. It is important that
the script return an answer in prompt fashion. Any significant processing
should be queued for later.
[nl] The arguments are the same as those for [const devicearrival] when
the device source type is [const handle].
[nl]
Note this notification is only delivered when the [cmd -handle] option
is used. The application can therefore easily use the notifier id to
associate the notification with a specific device. If the callback script
returns anything other than [const deny], it should first close all open
handles on the device, including the one passed as the argument value
for the [cmd -handle] option. Otherwise, the device removal will fail.

[opt_def [const devicequeryremovefailed]] 
A request to remove a device was canceled,
either because an application denied it or there were open handles to
the device. Additional arguments are the same as [const devicequeryremove].

[opt_def [const deviceremovecomplete]] Removal
of a device or media has been completed. For physical devices this means
the device has been physically disconnected. For volumes, this indicates
the volume has been dismounted.
Additional arguments are identical
to those of [const devicearrival].

[opt_def [const deviceremovepending]] A device is being removed and not 
available. Additional arguments are identical to those of [const devicearrival].

[opt_def [const devicetypespecific]] An event specific to the type of
device. Additional arguments are identical to those of [const devicearrival].

[opt_def [const devnodes_changed]] The system device tree has
been modified.  Windows does not provide any additional detail about
the change and it is up to the application to examine the device tree
components of interest.

[opt_def [const querychangeconfig]] Request to change
the current dock/undock configuration. The application can allow or
deny the request.
The command has no additional arguments.
See [const devicequeryremove] for more detail on how the script should
respond.

[opt_def [const userdefined]] A user defined event
sent by an application using BroadcaseSystemMessage. An additional argument
specifies the name of the event (vendor defined).

[list_end]
[nl]
This command requires a threaded build of Tcl and will raise an exception
on non-threaded builds.

[call [cmd stop_device_notifier] [arg MONITORID]]
Cancels monitoring of device changes. [arg MONITORID]
which must be an identifier previously
returned by [uri \#start_device_notifier [cmd start_device_notifier]].

[call [cmd unlock_media] [arg DEVICE]]
Unlocks the media in a device with removable media such as a CD-ROM
which had been previously locked with [uri #lock_media [cmd lock_media]].
[arg DEVICE] should be of the form [arg X:], [arg X:\\], [arg X:/]
where [arg X] is a drive letter, or a physical disk path as returned
by the [uri #find_physical_disks [cmd find_physical_disks]] command,
or [const cdrom], in which case the first CD-ROM in the device list
is unlocked.

[list_end]

[keywords device "device events" "CD-ROM insertion" "media change" "USB devices" "ioctl" "device ioctl"]

[manpage_end]
