<HTML>
<HEAD>
<TITLE>Device Console Scripting</TITLE>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
<META content="Microsoft FrontPage 5.0" name=GENERATOR>
</HEAD>
<BODY link=#0000ff><FONT face=Verdana size=5>
<H2>Device Console Scripting</H2></FONT><FONT face=Verdana size=2>
<P><SPAN style="COLOR: #ff0000; FONT-FAMILY: Arial; FONT-SIZE: 10pt">[This is
preliminary documentation and subject to change.]</SPAN></P>
<H3>SUMMARY</H3>
This document accompanies the Device Console COM Objects. The instructions herein apply to the Windows Whistler operating
system.
<p>The COM objects described in this document allow device query and management
using any COM aware language, for example, Visual Basic, VBScript and JScript.
<H3>HOW IT WORKS</H3>
<p>Right-click on "devcon.inf" and click "install". The COM objects will be
installed and made available for use. The following document describes the
objects available and samples on how to use them in context of VBScript.<h3>COM
Objects</h3>
<h4>DevCon.DeviceConsole {2F4D685C-7304-45F1-8075-443255A11156}</h4>
<p>Root object that can be created via CreateObject either locally or remote.<h5>Properties</h5>
<p>RebootRequired (Get/Set)<blockquote>
<p>This property is set if any derived objects indicate a reboot is required.</blockquote>
<h5>Methods</h5>
<p>AllDevices(<i>[flags]</i>,<i>[machine]</i>)<blockquote>
<p>Returns a <i>Devices </i>collection of all devices for local or specified
machine. Flags include 1 (Include not-present devices), 2 (In context of current
hardware profile rather than globally).</blockquote>
<p>DevicesBySetupClasses(<i>classList</i>,<i>[flags]</i>,<i>[machine]</i>)<blockquote>
<p>Returns a <i>Devices</i> collection of all devices of the specified setup
classes, otherwise similar to AllDevices. The classes may either be GUID's in
string form or class names. ClassList may be either a single string, a
collection of strings or an array of strings.</blockquote>
<p>DevicesByInterfaceClasses(<i>classList</i>,<i>[flags]</i>,<i>[machine]</i>)<blockquote>
<p>Returns a <i>Devices</i> collection of all devices that currently support any
of the specified interface classes. Interface classes must be specified as
GUID's in string form. Classlist may be either a single string, a collection of
strings or an array of strings.</blockquote>
<p>DevicesByInstanceIds(<i>idList</i>,<i>[machine]</i>)<blockquote>
<p>Same as CreateEmptyDeviceList followed by an "Add" on that device list.</blockquote>
<p>SetupClasses(<i>[classList]</i>,<i>[machine]</i>)<blockquote>
<p>Create a <i>SetupClasses</i> collection from the specified classlist.
Classlist may be either a single string, a collection of strings or an array of
strings. If classlist is omitted or is "", all classes for local/specified
machine is returned.</blockquote>
<p>CreateEmptyDeviceList(<i>[machine]</i>)<blockquote>
<p>Create a <i>Devices</i> collection that contains no devices for specified
machine. Creating the collection object this way (or by any of the other methods
in this object) associates the collection with this object and allows child
objects to be associated with this object. Creating the<i> </i>collection object
directly will not associate it with this object or a machine.<i> </i>
</blockquote>
<p>CreateEmptySetupClassList(<i>[machine]</i>)<blockquote>
<p>Create a <i>SetupClasses</i> collection that contains no setup classes for
specified machine. Creating the collection object this way (or by any of the
other methods in this object) associates the collection with this object and
allows child objects to be associated with this object. Creating the collection
object directly will not associate it with this object or a machine.</blockquote>
<p>UpdateDriver(<i>scriptName</i>,<i>hardwareId</i>,<i>[flags]</i>)<blockquote>
<p>Updates all devices that have specified<i> </i>hardwareId with best<i> </i>
driver in either specified script or system scripts (currently only INF files
are supported). A failure must be caught with appropriate error handling. Reboot
status can be checked via RebootRequired property. Appropriate permissions are
required.</blockquote>
<p>CheckReboot<blockquote>
<p>Prompts user for reboot if one is required. Reboots machine if user says ok,
otherwise returns. Appropriate permissions are required.</blockquote>
<p>RebootReasonHardware<blockquote>
<p>Unconditionally reboots the machine logging the reason as planned "hardware".
Appropriate permissions are required.</blockquote>
<p>AttachEvent(<i>event,handler</i>)<blockquote>
<p>Attach an event handler for the specified <i>event</i>. This function returns
'true' to indicate success. <span style="background-color: #FFFF00">currently no
other value is returned.</span> <i>Handler</i> is a function pointer. If
multiple handlers are specified, there is no guarantee on order of execution. In
VBScript, the <i>handler</i> parameter must be obtained using "getRef". The
following events are currently defined:<blockquote>
<table border="0" cellpadding="4" style="border-collapse: collapse" bordercolor="#111111" cellspacing="4">
<tr>
<td><b>Event name</b></td>
<td><b>Parameters</b></td>
<td><b>Action</b></td>
</tr>
<tr>
<td>OnDeviceNodesChanged</td>
<td><i>none</i></td>
<td>Indicates a device change (inserted/deleted/started/stopped) akin to
DBT_DEVNODES_CHANGED.</td>
</tr>
</table>
</blockquote>
</blockquote>
<p>DetachEvent(<i>event,</i><i>handler</i>)<blockquote>
<p>Detach event handler previously attached by AttachEvent. <i>Handler</i> and
<i>event</i> must be exactly the same as that specified in AttachEvent.</blockquote>
<h4>DevCon.Strings {BFDE9AEE-9418-42C0-8FA2-8B04C31ECDC7}</h4>
<p>Root object that can be created via CreateObject, also may be returned by
methods/properties. Provides a dynamic collection of strings. This dynamic
collection may be enumerated and/or indexed. Default method is "Item".<h5>
Properties</h5>
<p>CaseSensative (Get/Set)<blockquote>
<p>Normally the strings collection is lenient on case when indexing by string or
when finding strings. Leniency may be changed using this property. All strings
are stored case sensitive.</blockquote>
<p>Count (Get)<blockquote>
<p>Number of items in the collection. The Collection is indexed 1..Count
inclusive.</blockquote>
<h5>Methods</h5>
<p>Item(<i>[index/value]</i>) (Default)<blockquote>
<p>If no index specified, a snapshot of the collection is returned as a 1-based
array, otherwise the indexed string is returned. Either a numerical or string
index may be specified.</blockquote>
<p>Add(<i>items</i>)<blockquote>
<p>A string, collection of strings or array of strings may be added to the
collection. Multi-dimension arrays are flattened.</blockquote>
<p>Insert(<i>index/value</i>,<i>items</i>)<blockquote>
<p>A string, collection of strings or array of strings may be inserted before
the specified index (which may be a string in the collection or a numeric
index).</blockquote>
<p>Remove(<i>index/value</i>)<blockquote>
<p>Remove a string either by numeric index or by value.</blockquote>
<p>Find(<i>value</i>)<blockquote>
<p>Returns index of string if it exists, otherwise 0.</blockquote>
<h4> </h4>
<h4>DevCon.SetupClasses {84524499-52D7-4336-8A5D-EC6FE6A9C8DE}</h4>
<p>Root object that can be created via CreateObject (although creation via
DeviceConsole is preferred). Provides a dynamic collection of setup classes.
This dynamic collection may be enumerated and/or indexed. Default method is
"Item". This object may be associated with a machine and is typically associated
with a DeviceConsole object.<h5>Properties</h5>
<p>Count (Get)<blockquote>
<p>Returns number of SetupClass objects in the collection.</blockquote>
<h5>Methods</h5>
<p>Item(<i>index/guid</i>) (Default)<blockquote>
<p>Returns <i>SetupClass</i> object at specified index. Index is 1-based
numeric, or the class GUID may be supplied.</blockquote>
<p>Add(<i>classNames</i>)<blockquote>
<p>Add one or more classes to the collection. If a single GUID string is
specified, then only one SetupClass object will be added. If a class name is
specified, it is possible for multiple SetupClass objects to be associated with
the class name.</blockquote>
<p>Remove(<i>index/guid</i>)<blockquote>
<p>Remove a class from the collection.</blockquote>
<p>Devices(<i>[flags]</i>)<blockquote>
<p>Return <i>Devices</i> collection that contains the union of the devices of
all the device classes specified in this collection.</blockquote>
<h4> </h4>
<h4>DevCon.SetupClass</h4>
<p>A single object in the SetupClasses collection. Inherits any information
associated with the SetupClasses collection it was derived from. Default
property is "Guid".<h5>Properties</h5>
<p>Guid (Get, Default)<blockquote>
<p>Returns class Guid.</blockquote>
<p>Name (Get)<blockquote>
<p>Returns simple name of the setup class.</blockquote>
<p>Description (Get)<blockquote>
<p>Returns class description.</blockquote>
<p>Security (Get/Set)<blockquote>
<p>Default device security for class in SDDL format. Setting it to null or
nothing will delete setting.<span style="background-color: #FFFF00"> Not yet
implemented.</span></p>
</blockquote>
<p>DeviceTypeOverride (Set/Get)<blockquote>
<p>Default device type for class (eg FILE_DEVICE_CDROM = 0x02). Setting it to
null or nothing will delete setting.<span style="background-color: #FFFF00"> Not
yet implemented.</span></blockquote>
<p>ForceExclusive (Set/Get)<blockquote>
<p>If TRUE, sets default to force all devices in the class to only be opened in exclusive mode.
Setting it to null or nothing will delete setting.<span style="background-color: #FFFF00">
Not yet implemented.</span></blockquote>
<p>CharacteristicsOverride (Get/Set)<blockquote>
<p>Allows forcing (setting) of FILE_REMOVABLE_MEDIA (1) FILE_READ_ONLY_DEVICE
(2) FILE_FLOPPY_DISKETTE (4) FILE_WRITE_ONCE_MEDIA (8) FILE_DEVICE_SECURE_OPEN
(256)<p>If specified, sets default for the class. Setting it to null or nothing
will delete setting.<span style="background-color: #FFFF00"> Not yet
implemented.</span></blockquote>
<p>Machine (Get)<blockquote>
<p>Name of remote machine (usually prefixed by '\\').</blockquote>
<p> <h5>Methods</h5>
<p>Devices(<i>[flags]</i>)<blockquote>
<p>Return <i>Devices</i> collection for devices of this specific setup class.</blockquote>
<p>CreateEmptyDeviceList()<blockquote>
<p>Creates an empty device list that is locked to this setup class. (That is,
no devices can be added to it unless that device has the same setup class).</p>
</blockquote>
<p>RegRead(<i>keyPath</i>)<blockquote>
<p>If keyPath ends in
"\" then read key's default value, otherwise read named value. Supports reading
of REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ and REG_DWORD values.</blockquote>
<p>RegWrite(<i>keyPath</i>,<i>value</i>,<i>[type]</i>)<blockquote>
<p>If keyPath
ends in "\" then write key's default value, otherwise write named value.
Supports writing of REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD and
REG_BINARY values. If type is specified, it should be a string "REG_SZ", "REG_EXPAND_SZ",
"REG_MULTI_SZ", "REG_DWORD" or "REG_BINARY" and explicitly indicates the type of
value to be written. If not specified, type is determined from value
(collections will be written as REG_MULTI_SZ, strings as REG_SZ, integers as
REG_DWORD). If "REG_BINARY" is specified, value must be numeric.</blockquote>
<p>RegDelete(keyPath)<blockquote>
<p>Delete class specific value.</blockquote>
<h4> </h4>
<h4>DevCon.Devices {176FAC5E-3A43-42A3-9CFC-157308934DF4}</h4>
<p>Root object that can be created via CreateObject (although creation via
DeviceConsole or derived objects is preferred). Provides a dynamic collection of
devices. This dynamic collection may be enumerated and/or indexed. This object
may be associated with a machine and is typically associated with a
DeviceConsole object. Default method is "Item".<h5>Properties</h5>
<p>Count (Get)<blockquote>
<p>Returns number of Device objects in the collection.</blockquote>
<h5>Methods</h5>
<p>Item(<i>index/instanceId</i>) (Default)<blockquote>
<p>Return specified Device object. Index is 1-based.</blockquote>
<p>Add(<i>instanceId/instanceIdCollection</i>)<blockquote>
<p>Add one or more devices with specified instance ID's to this collection. This operation
will fail if the specified device does not exist, or if the collection is locked
to a specific setup class and the devi ce is of a different setup class.</blockquote>
<p>Remove(<i>index/instanceId</i>)<blockquote>
<p>Remove a device from collection. Index is 1-based. Does not delete the device
itself.</blockquote>
<p>CreateRootDevice(<i>[hardwareId]</i>)<blockquote>
<p>Create a root-enumerated device and add to the collection. If the collection
is locked to a specific setup class, the new device is associated with that
setup class. The device will have the specified hardware id. Returns a Device object for the newly created device.</blockquote>
<h4> </h4>
<h4>DevCon.Device</h4>
<p>A single object representing a device. Usually associated with a
DeviceConsole object and may be associated with a specific machine. Default
property is "InstanceId"<h5>Properties</h5>
<p>InstanceId (Default,Get)<blockquote>
<p>Instance Id of the device.</blockquote>
<p>RebootRequired (Get/Set)<blockquote>
<p>Indicates if this device requires a reboot to start. Setting this property
will also set the RebootRequired property of the associated DeviceConsole object
if any.</blockquote>
<p>Description (Get)<blockquote>
<p>Description of device as it would appear in device manager. If friendly name
is available, that is returned instead.</blockquote>
<p>HardwareIds (Get/Set)<blockquote>
<p>Strings collection of all hardware Id's reported by the device. May be
modified for root-enumerated devices. Setting it to null or nothing will delete
it.</blockquote>
<p>CompatibleIds (Get/Set)<blockquote>
<p>Strings collection of all compatible Id's reported by the device. May be
modified for root-enumerated devices. Setting it to null or nothing will delete
it.</blockquote>
<p>ServiceName (Get)<blockquote>
<p>Name of FDO service.</blockquote>
<p>Class (Get)<blockquote>
<p>GUID of SetupClass that device is associated with.</blockquote>
<p>Manufacturer (Get)<blockquote>
<p>Name of manufacturer of device if known.</blockquote>
<p>FriendlyName (Get/Set)<blockquote>
<p>Friendly name of device. Setting it to null or nothing will delete it.</blockquote>
<p>LocationInformation (Get/Set)<blockquote>
<p>Informative information about where the device is located. Setting it to null
or nothing will delete it.</blockquote>
<p>UpperFilters (Get/Set)<blockquote>
<p>Strings collection of all upper filter services. Setting it to null or
nothing will delete it.</blockquote>
<p>LowerFilters (Get/Set)<blockquote>
<p>Strings collection of all lower filter services. Setting it to null or
nothing will delete it.</blockquote>
<p>EnumeratorName (Get)<blockquote>
<p>Indicates bus enumerator type.</blockquote>
<p>Security (Get/Set)<blockquote>
<p>Device security in SDDL format. Setting it to null or nothing will delete
it.</p>
</blockquote>
<p>DeviceTypeOverride (Set/Get)<blockquote>
<p>Allows device type to be specified (eg FILE_DEVICE_CDROM = 0x02). If
specified overrides class settings. Setting it to null or nothing will delete
it.</blockquote>
<p>ForceExclusive (Set/Get)<blockquote>
<p>If TRUE, forces the device to only be opened in exclusive mode. If specified,
overrides class settings. Setting it to null or nothing will delete it.</blockquote>
<p>CharacteristicsOverride (Get/Set)<blockquote>
<p>Allows forcing (setting) of FILE_REMOVABLE_MEDIA (1) FILE_READ_ONLY_DEVICE
(2) FILE_FLOPPY_DISKETTE (4) FILE_WRITE_ONCE_MEDIA (8) FILE_DEVICE_SECURE_OPEN
(256)<p>If specified, overrides class settings. Setting it to null or nothing
will delete it.</blockquote>
<p>IsRunning (Get)<blockquote>
<p>True if device is up and running.</blockquote>
<p>IsDisabled (Get)<blockquote>
<p>True if device is disabled.</blockquote>
<p>HasProblem (Get)<blockquote>
<p>True if device has any kind of problem.</blockquote>
<p>ProblemCode (Get)<blockquote>
<p>Non-zero problem code if available, otherwise 0 (including if the device has
a private problem).</blockquote>
<p>HasPrivateProblem (Get)<blockquote>
<p>True if device has a private problem that no code is available for.</blockquote>
<p>IsRootEnumerated (Get)<blockquote>
<p>True if device is root enumerated.</blockquote>
<p>IsDisableable (Get)<blockquote>
<p>True if device can be disabled.</blockquote>
<p>IsRemovable (Get)<blockquote>
<p>True if device supports being removed while OS is running.</blockquote>
<p>Machine (Get)<blockquote>
<p>Name of remote machine (usually prefixed by '\\').</blockquote>
<h5>Methods</h5>
<p>Delete<blockquote>
<p>Delete (remove) the device. If successful, this object is invalid and the
device is removed.</blockquote>
<p>Enable<blockquote>
<p>Enable the device. If reboot is required, it is reported through the
RebootRequired property.</blockquote>
<p>Disable<blockquote>
<p>Disable the device. If reboot is required, it is reported through the
RebootRequired property.</blockquote>
<p>Start<blockquote>
<p>Start a stopped device.</blockquote>
<p>Stop<blockquote>
<p>Stop a running device.</blockquote>
<p>Restart<blockquote>
<p>Stop and then Start a device (property-change). This may succeed in cases
where Stop-Start would not.</blockquote>
<p>HasInterface(<i>interfaceClass</i>)<blockquote>
<p>Return true if the device supports the specified interface (and that
interface is currently active).</blockquote>
<p>RegRead(<i>keyPath</i>)<blockquote>
<p>If keyPath is prefixed with "SW\" then read the devices software key. If it
is prefixed with "HW\" then read the devices hardware key. If keyPath ends in
"\" then read key's default value, otherwise read named value. Supports reading
of REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ and REG_DWORD values.</blockquote>
<p>RegWrite(<i>keyPath</i>,<i>value</i>,<i>[type]</i>)<blockquote>
<p>If keyPath is prefixed with "SW\" then write to the devices software key. If
it is prefixed with "HW\" then write to the devices hardware key. If keyPath
ends in "\" then write key's default value, otherwise write named value.
Supports writing of REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_DWORD and
REG_BINARY values. If type is specified, it should be a string "REG_SZ", "REG_EXPAND_SZ",
"REG_MULTI_SZ", "REG_DWORD" or "REG_BINARY" and explicitly indicates the type of
value to be written. If not specified, type is determined from value
(collections will be written as REG_MULTI_SZ, strings as REG_SZ, integers as
REG_DWORD). If "REG_BINARY" is specified, value must be numeric.</blockquote>
<p>RegDelete(keyPath)<blockquote>
<p>If keyPath is prefixed with "SW\" then delete the specified device software
value. If it is prefixed with "HW\" then delete the specified device
hardware value.</blockquote>
<p>CurrentDriverPackage<blockquote>
<p>Determine driver package that was used for device. Return a DriverPackage
object or "nothing" if no driver package found for this device.</blockquote>
<p>FindDriverPackages(<i>[pathList]</i>)<blockquote>
<p>Obtain a DriverPackages collection of all viable drivers by searching system
directories and specified pathList (string/collection/array) for driver
packages. PathList may contain directories to search for installation scripts,
or may specify installation scripts by name (currently only INF files).
Sub-directories are not searched. An empty collection is returned if no
compatible drivers were found. If a path list is specified, only those
files/directories are searched unless one of the paths is "*" (search default
paths).<p> </blockquote>
<h4>DevCon.DriverPackages</h4>
<p>A collection of Driver Packages for a specific device. This collection may be
enumerated and/or indexed. This object is always associated with a device.
Default method is "Item".<h5>Properties</h5>
<p>Count<blockquote>
<p>Number of drivers.</blockquote>
<h5>Methods</h5>
<p>Item(<i>[index]</i>)<blockquote>
<p>Returns a specific DriverPackage object. Index is 1-based.</blockquote>
<p>BestDriver<blockquote>
<p>Returns best DriverPackage object for device.</blockquote>
<p>Add(<i>[pathlist]</i>)<blockquote>
<p>Add more drivers. <span style="background-color: #FFFF00">Not implemented.</span><p> </blockquote>
<h4>DevCon.DriverPackage</h4>
<p>An individual driver package.<h5>Properties</h5>
<p>Description (Get)<blockquote>
<p>Default description for the device. (Note that this may be different to
DriverDescription).</blockquote>
<p>Manufacturer (Get)<blockquote>
<p>Manufacturer of the device.</blockquote>
<p>Provider (Get)<blockquote>
<p>Provider of the install script.</blockquote>
<p>Date (Get)<blockquote>
<p>Driver date (returned as a date/time type).</blockquote>
<p>Version (Get)<blockquote>
<p>Version of driver (returned as a string in format "a.b.c.d").</blockquote>
<p>ScriptFile (Get)<blockquote>
<p>Name of file that determines how driver is to be installed. Currently only
INF files are supported.</blockquote>
<p>ScriptName (Get)<blockquote>
<p>In context of INF files, this is the decorated "DDInstall" section.</blockquote>
<p>HardwareIds (Get)<blockquote>
<p>Zero or more hardware ID's returned as a collection of strings. These are
devices the package was designed for.</blockquote>
<p>CompatibleIds (Get)<blockquote>
<p>Zero or more compatible ID's returned as a collection of strings. These are
devices the package will work with.</blockquote>
<p>DriverDescription (Get)<blockquote>
<p>A description of the driver (vs. the default description of the device).</blockquote>
<p>Reject (Get/Set)<blockquote>
<p>Mark the driver that it should not be considered when using "BestDriver"
method in containing collection.</blockquote>
<p>IsClassDriver (Get)<blockquote>
<p>Indicates this is a class driver.</blockquote>
<p>IsCompatibleDriver (Get)<blockquote>
<p>Indicates this is a compatible driver.</blockquote>
<p>DescriptionIsDuplicate (Get)<blockquote>
<p>Indicates there is another driver with same description in the containing
collection.</blockquote>
<p>ProviderIsDuplicate (Get)<blockquote>
<p>Indicates there is another driver with same provider in the containing
collection.</blockquote>
<p>ExcludeFromList (Get)<blockquote>
<p>Exclude this driver when using (future) DisplayAndSelectDriver method on
the containing collection.</blockquote>
<p>FromInternet (Get)<blockquote>
<p>Indicates this driver is from the internet.</blockquote>
<p>NoDriver (Get)<blockquote>
<p>No physical driver will be installed with this driver package.</blockquote>
<p>OldDriver (Get)<blockquote>
<p>Driver presently/previously controlled device.</blockquote>
<p>OldInternetDriver (Get)<blockquote>
<p>Driver was from internet but source files are no longer available.</blockquote>
<p>Rank (Get/Set)<blockquote>
<p>Obtains/modifies ranking of driver prior to searching using "BestDriver"
method in containing collection. The value '0' indicates ideal driver. Values
0x8000-0xFFFF indicate an un-trusted driver.</blockquote>
<h5>Methods</h5>
<p>DriverFiles<blockquote>
<p>For an installed package, the files that are used by the driver. For other
drivers, the files that would be used by the driver once installed.</blockquote>
<p>Manifest<blockquote>
<p>Source location of the files. <span style="background-color: #FFFF00">Not
implemented correctly, needs rethinking.</span></blockquote>
<p> <h4>DevCon.DeviceIcon {514C3095-47E8-4B24-B831-FB1C22C1B1B6}</h4>
<p>ActiveX control to display a device/class icon. Control is windowless and
transparent.<h5>Properties</h5>
<h5>Methods</h5>
<p>ObtainIcon(<i>deviceObject</i>/<i>classObject</i>)</p>
<blockquote>
<p>Pass in a device or class object. An appropriate icon will be displayed.</p>
</blockquote>
<p> </p>
</FONT><FONT face="Courier" size="3"><H3>FEEDBACK</H3>
<P>We welcome your comments, problem reports and wish-list requests. Please
submit them by pointing your Internet browser to <A href="http://www.microsoft.com/ddk">http://www.microsoft.com/ddk</A>.
</FONT></P>
<P align=center><FONT face=Verdana size=2><A href="#top">Top of page</A></P></FONT>
<TABLE border=0" cellSpacing="0" width="624">
<TR>
<TD bgColor="#00ffff" height="2" vAlign="middle"></TD></TR></TABLE>
<FONT face="MS Sans Serif" size=1>
<P>© Microsoft Corporation 2001</FONT><FONT face=Verdana size=2>
</P></FONT>
</BODY>