Deploying Windows XP Using Windows Product Activation

Published: November 01, 2001 | Updated: May 21, 2003

By Gerald Maffeo

Microsoft Corporation

Abstract

Microsoft® Windows® Product Activation (WPA) is aimed at reducing casual copying and hard disk loading. It applies primarily to 32-bit retail and system builder systems. Activation is not needed for 64-bit systems, or for customers using Microsoft volume licensing programs, such as Select or Open Licensing. Most large original equipment manufactures (OEM) will ship pre-activated systems.

This article is intended for administrators who need to activate Windows XP on machines as part of a large scale deployment.

On This Page

Acknowledgements
Introduction
Automation Overview
Unattended Activation
Sysprep Activation Rollback
Scripted Activation
Scripted Activation—Putting It All Together
Generic Product Keys
Summary
Related Links

Acknowledgements

Michael Kessler, Technical Editor, Microsoft Corporation

Introduction

Microsoft® Windows® Product Activation (WPA) is an anti-piracy technology designed to reduce casual copying and hard disk loading. WPA will apply to all 32-bit versions, except volume licensing, and to all distribution channels.

WPA is primarily of interest to retailers and System Builders for the following reasons:

  • Direct original equipment manufacturers (OEMs) usually choose to implement a version of WPA that will be locked to a machines firmware (BIOS). This bypasses activation by effectively pre-activating these machines.

  • Windows Product Activation is not needed in 64-bit versions of Windows XP. (Considering this, none of the automation functionality described in this article is relevant to 64-bit systems.)

  • Volume Licensing (VL) media—often referred to as select media—do not require activation. As a result, VL customers (Enterprise, Select, Campus, School, and Open) will probably not find much applicable information in this article. Setup does require entry of an organization's unique product key, which is generally provided in an answer file. Note: In the past, VL customers often used retail and VL media interchangeably. Windows XP no longer permits this: retail media must now be installed using retail product keys, while VL media must be installed using VL product keys. The ProductID (PID), discussed below, can be used to determine whether the correct media is installed on a machine.

  • Evaluation media do not support WPA automation and are not considered in this article.

How WPA Works

WPA works by associating a machine's PID (which is derived from the product key) to the hardware configuration. It does this by creating an installation ID. The installation ID comprises the PID and a "hardware hash," which is derived from a number of elements that characterize the machine. It also includes a random component that is generated each time it is requested.

In order to activate the machine, the installation ID is sent to a Microsoft license clearinghouse, which validates it. The clearinghouse returns a corresponding confirmation ID that is then used to activate the machine. After Windows XP has been activated, reactivation should only be necessary if the operating system is completely reinstalled, or if machine's hardware is substantially changed.

Users must activate Windows XP with their unique product keys within the defined grace period. For the released product, this is 30 days from the time the system is installed—MSDN versions have 60 days. After expiration, Windows will disallow interactive logons until the system is activated. The machine is otherwise fully functional (services are still loaded and running), and the Windows Management Instrumentation (WMI) automation mechanisms are still available. (WMI is a management infrastructure in Windows that supports monitoring and controlling system resources through a common set of interfaces.)

Validating Automated WPA

Microsoft's Information Technology Group (ITG) has validated the fully automated solution described below in the Scripted Activation—Putting It All Together section. It did this by successfully deploying over 100,000 machines (cumulatively) since Release Candidate 1 (RC1) of Windows XP. This process ensured that the built-in Windows Management Instrumentation (WMI) activation feature works as intended when using WPA.

Automation Overview

Not every Windows installation is done manually. Large scale deployments would be too costly and time-consuming if an administrator had to personally set up large numbers of machines. Such installations are therefore usually automated, using unattended or remote (RIS, SMS, etc.) processes. And administrators often will not want end users to personally activate their machines. WPA automation methods in Windows XP are designed to support automated deployments and accommodate these scenarios.

Note Most enterprise customers will deploy volume licensing media and will not need WPA automation.

WPA Automation Options

An administrator can choose whether to automatically activate a machine during setup or to defer activation to a later time. The WPA automation options presented in this article include:

  • Unattended Activation (Setup) – WPA supports the use of unattended answer files to set product keys, set temporary proxy settings, and to auto-activate during setup.

  • Sysprep Activation Rollback – WPA adds activation rollback to standard sysprep to support drive imaging as a deployment option.

  • Scripted Activation (Post-setup) –WPA's WMI provider supports scriptable, post-setup automation to query activation-related properties and to activate the machine—all on a fully automated, unattended basis.

Automating WPA—Something to Consider

One of the difficulties of automating activation during setup is that a machine's unique product key must be specified, either in the answer file itself, or in a uniqueness database file (UDF). Since a UDF is not commonly used, some administrators might therefore choose to generate a machine-specific answer file with the required product key on demand. This is not a Microsoft-provided feature and would require a customer-provided utility. Further, there is no guarantee that activation will actually succeed during setup, thereby limiting its value. The most useful deployment methods will therefore employ sysprep (for imaged systems) and post-setup scripted activation.

Using Product Keys During Setup

A product key of the correct type (retail, volume, or OEM, as well as the correct full or upgrade type) is always required during setup. For activation media, it is possible to enter a generic product key of the correct type and then change it to the required machine-specific product key at a later time. You can use the keys provided in the Generic Product Keys section below. These keys cannot be activated, since they are blocked at the clearinghouse. They do however permit setup to complete and start the activation timer.

Note: WPA provides both manual and automated methods to correct the product key before the products grace period expires.

Unattended Activation

If your installation scenario requires activation to be completed during setup, you can use an unattend answer file.

Unattend Answer File

An unattend answer file is a text file that is used in conjunction with Setup to bypass normal setup prompts. An unattend file can enter the product key automatically; configure the proxy setting; and then auto-activate the system on behalf of the end user, either through the target machine's local area network or default Internet connection.

In order to complete a successful unattended activation, the machine being set up must of course have Internet connectivity, either directly or through a firewall. An administrator must first configure the answer file appropriately.

Types of Answer Files

There are several variants of answer files. These include:

  • Support for manual invocation

  • CD installation

  • Mini-setup

  • Remote Installation Services (RIS)

Note: Discussion of unattended setup is beyond the scope of this document. Extensive documentation for Setup Manager and unattended installation is available on the installation CD. Targeted documentation is also available on OEM pre-installation kit CDs and accompanying RIS tools. See the section below for specific references.

Unattended Setup— An Example

A common way to use an answer file (for example unattend.txt) during an unattended installation is to invoke the Winnt32 /U:<answerfile> command.

Listing 1 below illustrates an unattend file that will accomplish a fully automated activation during setup using the above command.

Note: Syntax varies depending on the type of setup and the required answer file.

In this example only the highlighted lines specifically relate to activation. Other parameters may not apply or be appropriate to your needs. Refer to the documentation for complete information.

Listing 1—unattend.txt

[Unattended]
Unattendmode = FullUnattended
Filesystem = LeaveAlone
TargetPath = *
Win9XUpgrade = No
NtUpgrade = Yes AutoActivate = Yes
ActivateProxy = Proxy [userdata]
ProductKey =  PXRQ3-7VPMV-CQWXR-8Y4KX-RD786
[Branding]
BrandIEUsingUnattended = Yes [Proxy]
Proxy_Enable = 1
Use_Same_Proxy = 1
HTTP_Proxy_Server = myproxyserver:80
Proxy_Override = <local>

Three Important Items

There are three important items related to activation, each of these are highlighted in the Listing 1— unattend.txt example above:

Setting the Product Key

The above example is for illustration only because it uses a generic beta product key which cannot be activated. You must replace the generic product key used in the above example with your machine-specific product key in order to be able to activate during setup. The product key is generally found on the CD sleeve for retail media. See the Generic Keys section below for the appropriate keys for your installations.

Note: If you are upgrading, be sure to use the correct key for Windows XP—not a key you received for a previously installed operating system. Only product keys distributed for use with Windows XP can be used with Windows XP.

Setting the Proxy

This parameter, and the optional proxy section, may be required if your machine is connected to the Internet through a firewall. If your network supports Web Proxy Auto-Discovery (WPAD), you may be able to disregard this, however not all subnets may have implemented WPAD support. Listing 1 above illustrates a computer that requires the proxy setting to be configured. You must replace the proxy server name and port with one that matches your environment.

Note: The Branding section is required for the proxy setting to take effect.

Setting the AutoActivate Parameter

Use AutoActivate=Yes in order to request activation during setup—this does not guarantee a successful activation. To verify whether activation was successful, you can do one of the following:

  • Check the Application Event log.

  • Attempt to launch activation after logging on.

  • Use a WMI script, as described later in this article, to check the ActivationRequired property.

Sysprep Activation Rollback

Sysprep is a tool designed for deploying Windows XP on multiple computers. Typically, you set up a master image on a computer's hard disk, run sysprep, and then duplicate the hard disk. This master image will usually be used to create "cloned" images for a fairly long period of time—certainly well beyond the standard activation grace period.

Sysprep Supports Cloning

In order to support cloning scenarios using activation media, sysprep can roll back the activation grace period up to three times.

When an image that was prepared with sysprep is rebooted, its activation timer will restart with the full grace period. After the third time, however, the activation timers will no longer be reset. Sysprep can be repeated any number of times, but the activation rollback will only occur up to three times. This process is completely automatic and requires no action on your part.

Note: A master can be used to create additional and more specific levels of master images, subject to the three activation-rollback limit.

Activation Rollback Limitations

Activation rollback is not supported on pre-release beta media, post-release evaluation media, or MSDN media. It is also not available on volume licensing media.

Note: Detailed discussion of sysprep is outside the scope of this article. The sysprep tools, including extensive documentation, are available on both the release CD and the OEM Pre-installation Kit (OPK). See the Related Links section below for further information.

Scripted Activation

As an administrator, you may want to activate your users' retail Windows XP installations after setup, using command-line scripts. (Volume Licensing media do not require activation, as mentioned above.)

Automating Complete Activation

You can automate activation completely so that your connected users are totally unaware of it. You accomplish this by using WPA's WMI provider. Using the WPA provider, you can:

  • Query activation-related properties

  • Set new product keys

  • Request activation

Two primary classes are provided for this purpose:

  • Win32_WindowsProductActivation contains the above-mentioned functions.

  • Win32_Proxy class is used to query and set proxy settings.

Note: Detailed documentation for the above mentioned classes, as well as error constants, is included in the platform SDK referred to in the Related Links section below.

Sample Visual Basic Scripts

This remainder of this section provides sample Visual Basic (VB) scripts (.vbs) that illustrate how to use WPA's scripting facilities.

Note: These scripts have been formatted for readability. To keep the example scripts simple, error handling code is not shown, but should be included in production scripts.

win32_WindowsProductActivation—Properties

Listing 2 below is a simple VB script that displays all properties supported by the win32_WindowsProductActivation class for the machine. You can run this script (after removing the white space added for readability) with "Cscript wpa_properties.vbs" for text-mode operation, or "Wscript wpa_properties.vbs" for windowed operation.

Listing 2 – wpa_properties.vbs

for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
   InstancesOf ("win32_WindowsProductActivation")
   WScript.Echo
      Obj.ServerName,
      Obj.ProductID,
      Obj.ActivationRequired,
      Obj.RemainingGracePeriod,
      Obj.RemainingEvaluationPeriod
next

The platform SDK contains complete details for these properties.

win32_WindowsProductActivation—Properties

The following descriptions summarize each property referred to in Listing 2 above and provides useful deployment information:

  • ServerName uniquely identifies the computer. This value is either its fully qualified domain name (FQDN) or its IP Address.

  • ProductID (PID) contains a nine-digit sequence number, sssssssss, extracted from the product key that was used to install the system. It has the format xxxxx-sss-ssssssx-xxxxx for all systems except for OEM, which have xxxxx-OEM-xxssssx-sssss. You can also view the computer's PID by clicking Start, Control Panel, System and looking under Registered To: under the General tab.

  • ActivationRequired is 1 (true), if the computer must be activated within the number of days indicated by RemainingGracePeriod. Otherwise it is 0 (false).

  • RemainingEvaluationPeriod only has meaning for beta or evaluation media and is the number of days left in the evaluation. Otherwise, it has the largest possible integer value (2147483647).

win32_WindowsProductActivation—SetProductKey

The recommended method to bulk-deploy systems that require activation is to include a Microsoft-provided, generic product key in an answer file during system setup. (See Generic Product Key below.) This temporary generic key cannot be used to activate the computer and must be replaced by each individual computer's product key prior to the expiration of the activation grace period. The win32_WindowsProductActivation class provides the SetProductKey method to set the computer's key.

Determining Whether the Product Key Needs to be Changed

You can use the ProductID property to determine whether the product key used to install the computer was the generic key and therefore needs to be changed. This is done by comparing the ProductID's sequence number to the sequence number for the generic product key. The Mid() function extracts the sequence number and then compares it with the known value.

This script would typically run as part of each computer's logon script. Listing 3 below provides an example of how to accomplish this using a generic beta product key and corresponding sequence number—this example is for illustration purposes only and applies only to non-OEM versions.

See the Generic Product Keys section below for the appropriate keys and corresponding sequence numbers for your installations

Note In order for the Listing 3—wpa_productkey.vbs script to be useful, you will first need to capture into a database the product keys for all computers that you will deploy, and provide an access method to extract each key as needed. That process is beyond the scope of this article.

How wpa_productkey.vbs Works

  • Listing 3 first obtains an instance of the win32_WindowsProductActivation class for the system.

  • It then queries its ProductID, extracts the sequence number, and compares it with the generic value.

  • If they differ, the product key must already have been changed, so no further action is necessary.

  • If they are the same, a machine-specific product key is obtained using GetMyProductKey (this is a customer-provided function) and then installed on the target machine using the SetProductKey method.

Listing 3—wpa_productkey.vbs

'blocked genericProdKey = "PXR3-7VPMV-CQWXR-8Y4KX-RD786"
const genericSeqNum  = "010-053298"
myProdKey = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
         ' must be replaced with user's unique PK
for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
      InstancesOf ("win32_WindowsProductActivation")
      'Does PID's sequence number match generic value?
      If Mid(Obj.ProductID, 7, 10) = genericSeqNum Then
             'Sequence numbers match:
             ' Get new Product Key from database
             ' user-provided method:
             ' myProdKey = GetMyProductKey()
             'Set machine-specific product key
             Obj.SetProductKey(myProdKey)
      end if
next

win32_WindowsProductActivation—ActivateOnline

The ActivateOnline method supports activation of a machine that has Internet access. This is equivalent to the Internet activation method in the manual user interface and uses the HTTPS protocol to communicate with the Microsoft clearinghouse server. If necessary, you should first use the win32_Proxy SetProxySetting method described below in order to connect through a firewall.

How wpa_activateonline.vbs Works

Listing 4 should typically be run as part of each machine's logon script.

  • It first queries the ActivationRequired property.

  • If the machine has already been activated, then no further action is required.

  • Otherwise, the script calls the ActivateOnline method.

Listing 4 – wpa_activateonline.vbs

for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
      InstancesOf ("win32_WindowsProductActivation")
      if Obj.ActivationRequired <> 0 then
            'If necessary, save/set proxy
            Obj.ActivateOnline()
            'If necessary, restore proxy
      end if
next

win32_WindowsProductActivation—ActivateOffline

A multi-step process is needed to activate machines that are not connected to the Internet. This is equivalent to the telephone activation procedure that is provided in the manual user interface.

Activating Machines Not Connected to the Internet

To activate a machine not connected to the Internet perform the following steps:

  • Obtain the InstallationID through the GetInstallationID method.

  • Place a phonecall to Microsoft's activation call center to obtain a corresponding ConfirmationID.

  • Submit the ConfirmationID to the machine using the ActivateOffline method.

Calling the activation center, reading the Installation ID, and obtaining the ConfirmationID is a manual process for which no automation solution is currently available. It makes the most sense to call periodically, with as many InstallationIDs as are available. Use the manual user interface for telephone activation to determine the correct telephone number to call for your country.

Listing 5 below illustrates the use of the GetInstallationID method. It returns a unique InstallationID string in myIID each time it is called.

Listing 5—wpa_getIID.vbs

for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
      InstancesOf ("win32_WindowsProductActivation")
      if Obj.ActivationRequired <> 0 then
            result = Obj.GetInstallationID(myIID)
            WScript.Echo "InstallationID = " & myIID
      end if
next

Listing 6—wpa_ActivateOffline.vbs

Listing 6 completes offline activation through the use of the ActivateOffline method.

myConfID="012345678901234567890123456789012345678901"
for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
   InstancesOf ("win32_WindowsProductActivation")
   result = Obj.ActivateOffline (myConfID)
next

What Makes Offline Activation Fail

Offline activation using a ConfirmationID corresponding to a given call to the GetInstallationID() method will fail for the following reasons:

  • There have been intervening calls to GetInstallationID().

  • The telephone activation user interface screen has been used.

  • There have been intervening interactive logons—including Remote Administration and Remote Desktop, or through Terminal Services.

win32_Proxy—Properties

The win32_Proxy class is used to retrieve the current proxy setting for the context in which it is being run, as well as to set the proxy server and port to a new value. If you want to use WPA's ActivateOnline method to activate a machine that is connected to the Internet through a firewall, then you will first need to set its proxy. Before you set the proxy, you should first get and save its existing value, so that you can restore it once you are finished.

Listing 7 below illustrates how to retrieve the proxy server's current name and port setting.

Listing 7 – wpa_GetProxy.vbs

for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
   InstancesOf ("win32_Proxy")
   WScript.Echo
   Obj.ProxyServer,
   Obj.ProxyPortNumber
next

win32_Proxy—SetProxySetting

The SetProxySetting method is used to set the current proxy server and port to a new value for the context in which it is being run. Listing 8 below illustrates how you can set the proxy:

Listing 8 – wpa_SetProxy.vbs

myProxyServer="myproxy"
myProxyPort=80
for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").
      InstancesOf ("win32_Proxy")
      result = Obj.SetProxySetting(myProxyServer,myProxyPort)
            end if
next

Scripted Activation—Putting It All Together

The following sample script (WPA_Automation.vbs) illustrates how to activate a machine online from within a logon script. It assumes that the machine was initially set up using the generic product key.

How WPA_Automation.vbs Works

If a machine was initially set up using the generic product key, WPA_Automation.vbs performs the following steps:

  • It replaces the key with the machine-specific key, obtained through a call to the customer-provided function GetProductKey().

  • It then determines whether the machine needs to be activated.

  • If activation is necessary, it saves the current proxy setting, sets the required proxy, activates the machine, and then restores the original proxy.

WPA_Automation.vbs—Sample Script

'***************************************************************
' WMI Sample Script WPA_Automation.vbs (VBScript)
' This script demonstrates Windows Product Activation automation
'   if current PID is the generic PID (blocked at clearinghouse)
'      get machine-specific product key from database
'          (not included here)
'      call SetProductKey method
'   if activation is required (not activated yet)
'      save existing proxy setting
'      set proxy
'      call ActivateOnline method
'      restore saved proxy setting
'***************************************************************
ON ERROR RESUME NEXT
productKey = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
            'must be replaced with user's unique PK
'blocked genericPK = "PXRQ3-7VPMV-CQWXR-8Y4KX-RD786"
const seqNumber = "010-053298"
            'part of PID, derived from genericPK
actvProxyServer = "proxy"         'replace with values appropriate
actvProxyPort   = "80"         'to the customer environment
For Each wpaObj In GetObject("winmgmts:{impersonationLevel=impersonate}").
      InstancesOf ("win32_WindowsProductActivation")
      'Set new Product Key if the current PID's
      'Sequence Number matches the global PID (once only)
      If Mid(wpaObj.ProductID, 7, 10) = seqNumber Then
            WScript.Echo "Sequence Numbers match!"
            'Sequence Numbers match: get new Product Key from database
            'Get new Product Key from database"
            productKey = GetProductKey()
            WScript.Echo "Product Key: " & productKey
            'Set new Product Key
            result = wpaObj.SetProductKey(productKey)
            WScript.Echo "SetProductKey() returned = " & result
            If err <> 0 Then
                  WScript.Echo Err.Description, "0x" & Hex(Err.Number)
                  Halt
      End If
   End If         ' ProductKey check/set
   'If not yet activated, set proxy and activate the machine
   If wpaObj.ActivationRequired <> 0 Then
            serverName = wpaObj.ServerName
            WScript.Echo "ActivationRequired for " & serverName
            'Set proxy. First save existing proxy for later
            For Each proxyObj In
                  GetObject("winmgmts:{impersonationLevel=impersonate}").
                  InstancesOf ("win32_Proxy")
                  savedProxyServer = proxyObj.ProxyServer
                  savedProxyPort   = proxyObj.ProxyPortNumber
                  WScript.Echo "Saved Proxy: " & savedProxyServer &
                  ":" & savedProxyPort
            Next
            'Set temporary activation proxy
            For Each proxyObj In
                  GetObject("winmgmts:{impersonationLevel=impersonate}").
                  InstancesOf ("win32_Proxy")
                  result = proxyObj.SetProxySetting(actvProxyServer,actvProxyPort)
                  WScript.Echo "SetProxySetting() returned = " & result
                  If err <> 0 Then
                        WScript.Echo Err.Description,"0x" & Hex(Err.Number)
                        Halt
                  End If
            Next
            'Activate Machine
            result = wpaObj.ActivateOnline()
            WScript.Echo "ActivateOnline Method() returned = "& result
            If err <> 0 Then
                 WScript.Echo Err.Description, "0x" & Hex(Err.Number)
                 ' do not halt - need to reset proxy
        End If
        'Restore proxy to original setting
        For Each proxyObj In
              GetObject("winmgmts:{impersonationLevel=impersonate}").
              InstancesOf ("win32_Proxy")
              result = proxyObj.SetProxySetting (savedProxyServer,savedProxyPort)
              WScript.Echo "SetProxySetting Method() = " & result
              If err <> 0 Then
                        WScript.Echo Err.Description, "0x"& Hex(Err.Number)
                        Halt
                   End If
            Next
      End If
Next

Generic Product Keys

All of the examples provided above used a beta key for illustration purposes. The product keys listed in this section can be used with any of the answer files and scripted examples. They are blocked at the Microsoft clearinghouse and therefore cannot be used to activate any systems. They provide a number of days (assume 14 days) for you to complete the activation process.

It is absolutely essential that you use the correct type of key, which is a function of the platform type and the media. Choose the key and corresponding sequence number for your scripts from the following table:

Generic Product Keys

Applicability

Product Key

Sequence Number

Whistler Tech Beta Program
(All Platforms)

PXRQ3-7VPMV-CQWXR-8Y4KX-RD786

010053298

Windows XP
Home Edition
Full product

JKTVX-HCRXC-J2YC9-MX3K4-G9X26

005037750

Windows XP
Home Edition
Upgrade

C84VB-JYVFD-P7HF4-6KKRJ-7M6XH

010000182

Windows XP Professional
Full product

DR8GV-C8V6J-BYXHG-7PYJR-DB66Y

005072760

Windows XP Professional
Upgrade

FKTW8-Q7MJ7-JK6GW-9J9RV-HC3C2

010000212

Windows XP
Home Edition
System Builder (Full)

KGVXT-F9HVW-XGW9X-QVYVX-HQ9RD

120000613

Windows XP Professional
System Builder (Full)

TTGHK-3RC33-BT9DR-3BVYV-BTQ98

120000607

Summary

Large scale deployments of Windows XP would be too costly and time-consuming if an administrator had to personally set up large numbers of machines. Such installations are therefore usually automated, using unattended or remote (RIS, SMS, etc.) processes. WPA automation methods in Windows XP are designed to support automated deployments. If your installation scenario requires activation to be completed during setup, you can use an unattend answer file.

As an administrator, you may want to activate your users' retail Windows XP installations after setup, using command-line scripts. You can automate activation completely so that your connected users are totally unaware of it by using WPA's WMI provider. WMI lets you query activation-related properties, set new product keys, and request activation.

Microsoft's Information Technology Group (ITG) has validated the fully automated online activation solution described above in the Scripted Activation—Putting It All Together section. It did this by successfully deploying over 100,000 machines (cumulatively) since Release Candidate 1 (RC1) of Windows XP. This process ensured that the built-in Windows Management Instrumentation (WMI) activation feature works as intended when using WPA.

See the following resources for further information: