Universal Plug and Play

Purpose

Universal Plug and Play (UPnP) enables dynamic networking of intelligent appliances, wireless devices, and PCs. The UPnP Control Point API consists of a set of COM interfaces used to find and control UPnP devices.

Where Applicable

The Universal Plug and Play Control Point API enables developers to write applications that search for and control UPnP devices.

Developer Audience

The UPnP APIis used by a variety of applications, from scripts embedded in HTML pages to full-fledged C++ programs. UPnP Microsoft Visual Basic® (VB) and C++.

Run-Time Requirements

The UPnP Control Point API is used on computers running either Microsoft® Windows® Millennium or Whistler.

For more specific information about which operating systems support a particular function, refer to the Requirements sections in the documentation.

Overview of Universal Plug and Play

General information about Universal Plug and Play.

UPnP Control Point Overview

General information about the UPnP Control Point API.

Using the UPnP Control Point API

Sample code that shows how to develop applications that control UPnP devices.

UPnP Control Point Reference

Documentation of UPnP Control Point component interfaces, methods, and events.

Feedback

Make error reports and feature requests directly to Microsoft.

Microsoft Platform SDK, February 2001 Edition.
This content last built on Thursday, February 01, 2001.


Overview of Universal Plug and Play

Universal Plug and Play (UPnP) is an architecture for peer-to-peer network connectivity of intelligent appliances and other control points. It is designed to bring easy-to-use, flexible, standards-based connectivity to ad-hoc, managed, or unmanaged networks, whether these networks are in the home, small businesses, or attached directly to the Internet. Universal Plug and Play is a distributed, open networking architecture that uses existing TCP/IP and Web technologies to enable seamless proximity networking in addition to control and data transfer among networked devices.

UPnP is more than just a simple extension of the plug and play peripheral model. It supports zero-configuration, invisible networking and automatic discovery for a range of device categories from a wide range of vendors. This enables a device to dynamically join a network, obtain an IP address, and convey its capabilities upon request. Then other control points can use the UPnP Control Point API to learn about the presence and capabilities of other devices. A device can leave a network smoothly and automatically when it is no longer in use.

Universal Plug and Play is "universal" because there are no device drivers; it uses standard protocols instead. UPnP networking is media independent. UPnP applications are implemented using any programming language, and on any operating system. It enables vendor control over device UI through the browser, and also offers programmatic control to applications. It also enables developers to write their own UIs for devices, forgoing the vendor-provided interface.


Universal Plug and Play Control Point API

This section contains information about the UPnP Control Point API. The UPnP Control Point API provides a set of COM interfaces that allow applications to find and control UPnP devices.

  • About the UPnP Control Point API
  • Using the UPnP Control Point API
  • UPnP Control Point API Reference


About the UPnP Control Point API

Universal Plug and Play (UPnP) enables dynamic networking of intelligent appliances, PCs, and other control points. The dynamic networking is available over a variety of physical media. The Microsoft implementation of the UPnP Control Point API consists of a set of COM objects that are used to write applications and Web pages that find and control UPnP devices. For example, a UPnP-capable VCR can be controlled from a Web page that was specifically designed to control it. To extend this concept, developers can to control many appliances from a central, remote, or peer location.

Applications created with the UPnP Control Point API range from scripts embedded in HTML pages to full-fledged C++ programs. The UPnP Control Point API supports Microsoft® Visual Basic® (VB) development system, Microsoft Visual Basic® Scripting Edition (VBScript), and C++.

The following sections explain, in general, how the UPnP Control Point API works:

  • Control Point Basics
  • Finding Devices
  • Describing Devices
  • Controlling Devices
  • Finding Devices
  • Creating the Device Finder
  • Obtaining Service Objects
  • Querying State Variables


Control Point Basics

This section covers the basic information about UPnP control points:

  • What is the UPnP Control Point Object Model?
  • What are the Basic Actions of the Control Point API?


What is the UPnP Control Point Object Model?

The following illustration shows the basic UPnP Control Point object model.

Searching for devices with the Device Finder interface creates a Devices collection. A Devices collection contains zero or more Device objects. Applications can use the various Devices collection methods to work with individual Device objects.

Device objects must contain a Services collection that contains one or more Service objects. These service objects are used by applications to communicate with and control devices.


What are the Basic Actions of the Control Point API?

All control points perform the following tasks:

  • Find available UPnP devices on the network.
  • Determine which of these devices are of interest.
  • Issue control requests to the devices of interest and receive events generated by the devices.

An application must first find available UPnP devices on the network by performing a search. Because the search criteria defined by the UPnP architecture are fairly broad, the application may find more devices than are needed. The application must therefore examine the characteristics of the devices that were found to determine which ones most closely match the search criteria. The application can then issue control requests to those devices.

The following sections describe how to carry out these operations using the UPnP Control Point API:

  • Finding Devices
  • Describing Devices
  • Controlling Devices

For detailed documentation about each interface in the UPnP Control Point API, see the UPnP Control Point API Reference.


Finding Devices

Universal Plug and Play (UPnP) is a dynamic network architecture. UPnP allows devices to join and leave the network at any time. Because of this dynamic architecture, applications cannot rely on specific UPnP devices to be available at any given time. For this reason, UPnP applications (or control points) search the network to find devices that most closely match specified criteria and wait for device advertisement messages that indicate new devices have been added to the network.

The following are valid search criteria for UPnP devices:

  • device type
  • service type
  • unique device name (UDN)
  • all root devices

The device type and service type searches are typically used to find a class of devices with common characteristics. The unique device name search is used to find a specific device.

To search for devices, an application must first instantiate the Device Finder object. This object exposes the IUPnPDeviceFinder interface; its methods perform the searches that are described above.

The following sections describe the process of finding devices:

  • Creating the Device Finder
  • Asynchronous Searching
  • Synchronous Searching
  • Device Collections Returned By Synchronous Searches


Creating the Device Finder

The following examples demonstrate how to create an instance of the Device Finder object in C++, Visual Basic® and Scripting Edition (VBScript). The script languages use the programmatic ID (ProgID) UPnP.UPnPDeviceFinder to identify the Device Finder class. The C++ code uses the class identifier.

C++ Example

HRESULT hr = S_OK;
IUPnPDeviceFinder *pDeviceFinder = NULL;

hr = CoCreateInstance(CLSID_UPnPDeviceFinder,
                      NULL,
                      CLSCTX_INPROC_SERVER,
                      IID_IUPnPDeviceFinder,
                      (void **) &pDeviceFinder);

As this C++ example indicates, the Device Finder object exposes a default interface, IUPnPDeviceFinder. The methods of this interface perform searches according to the valid search criteria for a UPnP device. This interface is Automation capable, so its methods can be called by scripting code.

VBScript Example

Dim deviceFinder

Set deviceFinder = CreateObject( "UPnP.UPnPDeviceFinder" )


Asynchronous Searching

The Device Finder object enables both synchronous and asynchronous searches. Asynchronous searches return control to the calling application immediately. Then, the application is notified about each individual device as it is found, using a callback interface that the application has registered.

Asynchronous searching is best for graphical user interfaces, and applications that perform continuous monitoring.

The general structure of an asynchronous search is:

  1. Create a search object
  2. Start the search
  3. Return to the message loop
  4. Receive callback notifications and take the appropriate processing steps.
  5. When the search is no longer needed, cancel the search and release the associated objects.

Note In the callback code, an application cannot release the object it is receiving notification about, such as a new device, nor can the application cancel the search.

C++ Example

C++ applications must implement a callback object to pass to the search. See Searching Asynchronously in C++ for sample code that illustrates this action.

VBScript Example

VBScript code must pass the address of the callback function.

<head><title>async vbscript example</title></head>
<body>
<script language="VBScript">

Sub DeviceFinderCallback (device, UDN, calltype)

  select case calltype
    Case 0
      output = "Found: " & vbCrLf
      output = output & "DisplayName: " & device.FriendlyName & vbCrLf
      output = output & "Type: " & device.Type & vbCrLf
      output = output & "UDN: " & device.UniqueDeviceName & vbCrLf
      MsgBox output

    Case 1
      MsgBox "device removed: " & UDN

    Case 2
      MsgBox "search complete"

    end select
End Sub

Dim devicefinder
Dim findData

Set devicefinder = CreateObject("UPnP.UPnPDeviceFinder")

Sub StartFind()
  findData = devicefinder.CreateAsyncFind("upnp:rootdevice", 0, _
   GetRef("DeviceFinderCallback"))

  devicefinder.StartAsyncFind(findData)
End Sub

Sub StopFind()
  deviceFinder.CancelAsyncFind(findData)
End Sub
</script>

<input type="button" value="Start async search" onclick="StartFind">

<input type="button" value="Stop async search" onclick="StopFind">

</body>
</html>


Synchronous Searching

The Device Finder object enables both synchronous and asynchronous searches. Synchronous searches are completed and return control to the calling application only after all available devices are found. To perform a synchronous search, use one of the synchronous search methods of the IUPnPDeviceFinder interface. Synchronous searches are best for command-line interfaces. They are not recommended for graphical user interfaces, because the time required to complete them is often greater than nine seconds.

The IUPnPDeviceFinder::FindByType method searches by device or service type. This method takes a type URI as an input parameter and returns a collection of Device objects. A Device object represents an individual device.

The following examples demonstrate how to perform a synchronous search for devices in VBScript. Each script uses IUPnPDeviceFinder::FindByType, called with the type URI for the media player device type, urn:schemas-upnp-org:device:mediaplayer.v1.00.00. The method returns a collection of Device objects that corresponds to media player devices that were found. For information on extracting individual device objects from a collection, see Device Collections Returned By Synchronous Searches.

Search for Devices by Type in VBScript

Dim deviceFinder

Set deviceFinder = CreateObject( "UPnP.UPnPDeviceFinder" )

Dim devices

Set devices = deviceFinder.FindByType( "urn:schemas-upnp-org:device:multidisk-dvd", 0 )

Search for Device by Type in C++

The following example demonstrates a synchronous search for media player devices using C++. The function takes a pointer to the IUPnPDeviceFinder interface as input, and returns the IUPnPDevices interface pointer. The IUPnPDevices interface is the default interface of a device object collection.

The example first allocates a BSTR to represent the device type URI and then passes this to the IUPnPDeviceFinder::FindByType method. It also passes the address of a local IUPnPDevices pointer in the buffer in which the method then stores the collection of devices found. If the function call is successful, it returns the pointer to this collection.

IUPnPDevices *
FindMediaPlayerDevices(IUPnPDeviceFinder *pDeviceFinder)
{
    HRESULT         hr = S_OK;
    IUPnPDevices    * pFoundDevices = NULL;
    BSTR            bstrTypeURI = NULL;

    bstrTypeURI =
        SysAllocString(L"urn:schemas-upnp-org:device:multidisk-dvd");

    if (bstrTypeURI)
    {
        hr = pDeviceFinder->FindByType(bstrTypeURI,
                                       0,
                                       &pFoundDevices);

        if (SUCCEEDED(hr))
        {
            wprintf(L"FindMediaPlayerDevices(): "
                    L"Search returned successfully\n");
        }
        else
        {
            fwprintf(stderr, L"FindMediaPlayerDevices(): "
                     L"FindByType search failed - returned "
                     L"HRESULT 0x%x\n",
                     hr);
            pFoundDevices = NULL;
        }
        SysFreeString(bstr TypeURI)
    }
    else
    {
        fwprintf(stderr, L"FindMediaPlayerDevices(): "
                 L"Could not allocate BSTR for type URI\n");
    }

    return pFoundDevices;
}


Device Collections Returned By Synchronous Searches

Device collections are objects that contain one or more Device objects. A Device collection exposes the IUPnPDevices interface that provides methods and properties for traversing the collection and extracting individual device objects.

VBScript Example

VBScript applications can access the objects in the collection in two ways. First, they can traverse the elements sequentially using a for … next loop as shown in the following example:

for each deviceObj in devices

    'Do something interesting with deviceObj, such as
    'print the device name

next

In this example, the devices variable is assumed to have been initialized with the result of a prior search. The loop steps through the Device objects in the collection, assigning the variable deviceObj the value of each Device object in turn. The body of the loop can contain code that processes the Device object.

C++ Example

The following example shows the C++ code required to access the objects in a collection of device objects. The function shown, TraverseCollection, receives a pointer to the IUPnPDevices interface as an input parameter. This interface pointer could be returned by the FindByType method, or other Find methods, of the Device Finder object.

void TraverseCollection( IUPnPDevices * pDevices )
{
    HRESULT         hr = S_OK;
    IUnknown        * pUnk = NULL;

    // Get an enumerator from the devices collection.

    hr = pDevices->get__NewEnum(&pUnk);

    if (SUCCEEDED(hr))
    {
        IEnumVARIANT    * pEnumVar = NULL;

        // Get the IEnumVARIANT interface.

        hr = pUnk->QueryInterface(IID_IEnumVARIANT,
                                  (void **) &pEnumVar);

        if (SUCCEEDED(hr))
        {
            VARIANT varCurDevice;

            VariantInit(&varCurDevice);

            pEnumVar->Reset();

            // Traverse the collection.

            while (S_OK == pEnumVar->Next(1, &varCurDevice, NULL))
            {
                IDispatch   * pdispDevice = NULL;
                IUPnPDevice * pDevice = NULL;

                pdispDevice = V_DISPATCH(pvarDevice);

                hr = pdispDevice->QueryInterface(IID_IUPnPDevice,
                                                 (void **)
                                                   &pDevice);

                if (SUCCEEDED(hr))
                {
                    // Do something interesting with pDevice.

                    pDevice->Release();
                }

                VariantClear(&varCurDevice);
            };

            pEnumVar->Release();
        }
        else
        {
            wcerr << L"Could not get enumerator interface – "
                  << L"HRESULT 0x"
                  << setbase(16)
                  << hr << L"\n";
        }

        pUnk->Release();
    }
    else
    {
        wcerr << L"Could not get new enumerator - HRESULT 0x"
              << setbase(16)
              << hr << L"\n";
    }
}

The first step is to request a new enumerator for the collection using the _NewEnum property. This returns an enumerator as the IUnknown interface. The sample code invokes QueryInterface to obtain the IEnumVARIANT interface. The sample code then sets the enumerator to the beginning of the collection by invoking the Reset method. Finally, the sample code invokes the Next method to traverse the collection. The device objects in the collection are contained within VARIANT structures. These structures contain pointers to IDispatch interfaces on the device objects. To obtain the IUPnPDevice interface, the sample code invokes QueryInterface on the IDispatch interface.


Describing Devices

There are two ways to obtain device objects:

  • Using the IUPnPDescriptionDocument interface
  • Using the IUPnPDeviceFinder interface to obtain an IUPnPDevices interface

Both methods return Devices collections. Applications can then use the Device methods to retrieve properties about devices.

Applications can retrieve the following types of information:

  • Device hierarchy information, including root devices, parent devices, and child devices.
  • Device properties, including UDNs, uniform resource identifiers (URIs), and human-readable names.
  • Manufacturer information, including names and related Web pages.
  • Model information, including the name, number, UPC, serial numbers and device descriptions.
  • Display information, including the URL to control the device, and URLs from which icons are downloaded.
  • Services provided by a particular device.


Controlling Devices

UPnP devices are controlled by the services they expose. A UPnP service is the smallest controllable entity in the UPnP architecture. Devices expose one service for each primary function they can perform. Complex devices are typically composed of several simple services and other devices.

A service consists of a set of state variables and a set of actions an application can invoke that operate on those state variables. In the UPnP Control Point API, services are represented by Service objects that expose the IUPnPService interface.

The IUPnPService interface also allows applications to register a callback function with the service object. When the value of a service's state variable changes, the service object invokes the registered callback to notify the application of the change. Universal Plug and Play also invokes this callback to notify applications when a service instance has become unavailable. The service may become unavailable for a variety of reasons, including transient network failure.

For more information, see the following topics:

  • Obtaining Service Objects
  • Registering a Callback
  • Querying State Variables
  • Invoking Actions


Obtaining Service Objects

Device objects expose a property called Services that returns a collection of Service objects that contains one service object for each service exported by the device. Applications can traverse this collection sequentially, or request a particular service by using its service ID.

VBScript Example

The following example is VBScript code that extracts Service objects for two of the services exported by a device.

' Get the service objects
services = device.Services

Set appService = services( "urn:upnp-org:serviceId:DVDVideo" )
Set xportService = services( "urn:upnp-org:serviceId:AVTransport" )

The first line extracts the services collection from the Device object by querying the Services property. The next two lines obtain the two desired Service objects from the collection by specifying their service IDs. The services collection can also be traversed sequentially by using a for each … next loop.

C++ Example

The following example shows the C++ code required to obtain Service objects from a device. First, the sample code queries the IUPnPDevice::Services property on the interface that was passed to the function. This returns a service collection using the IUPnPServices interface. To obtain individual Service objects, use the Item method, and specify the requested service IDs. To traverse the collection sequentially, use the Reset, Next, and Skip methods. This example is similar to the example used to traverse the IUPnPDevices collection.

void
ExtractServices(IUPnPDevice * pDevice)
{
    HRESULT         hr = S_OK;
    IUPnPServices   * pServices = NULL;
    IUPnPService    * pAppService = NULL;
    IUPnPService    * pXportService = NULL;
    BSTR            bstrSvcId;

    // Get the services collection.

    hr = pDevice->get_Services(&pServices);

    if (SUCCEEDED(hr))
    {

        // Retrieve the "DVDVideo" service.

        bstrSvcId = SysAllocString(L"urn:upnp-org:serviceId:DVDVideo");

        if (bstrSvcId)
        {
            hr = pServices->get_Item(bstrSvcId, &pAppService);

            SysFreeString(bstrSvcId);
            bstrSvcId = NULL;

            if (SUCCEEDED(hr))
            {

                // Retrieve the "AVTransport" service.

                bstrSvcId = SysAllocString(L"urn:upnp-org:serviceId:AVTransport");

                if (bstrSvcId)
                {
                    hr = pServices->get_Item(bstrSvcId,
                                             &pXportService);

                    SysFreeString(bstrSvcId);
                    bstrSvcId = NULL;

                    if (SUCCEEDED(hr))
                    {
                        // Do something interesting
                        // with both service objects.

                        pXportService->Release();
                    }
                    else
                    {
                        wcerr << L"Could not get xport service "
                              << L"object - HRESULT 0x"
                              << setbase(16)
                              << hr << L"\n";
                    }
                }
                else
                {
                    wcerr << L"Could not Xport allocate service "
                          << L"ID string\n";
                }

                pAppService->Release();
            }
            else
            {
                wcerr << L"Could not get app service "
                      << L"object - HRESULT 0x"
                      << setbase(16)
                      << hr << L"\n";
            }
        }
        else
        {
            wcerr << L"Could not allocate app service ID"
                  << L" string\n";
        }

        pServices->Release();
    }
    else
    {
        wcerr << L"Failed to get services collection from "
              << L"device - HRESULT 0x"
              << setbase(16)
              << hr << L"\n";
    }
}


Registering a Callback

If the application requires notification when the value of a state variable changes or the service instance it represents becomes unavailable, the application must register a callback function. To register a callback function for the service object to invoke, use the IUPnPService::AddCallback method. This method can be used to register more than one callback.

Note Adding a callback in Visual Basic® (VB) is different from the method used in VBScript. The GetRef() function used in the VBScript is not available in VB. Therefore, a developer must create an IDispatch object that has the callback function as the default method. See Registering a Callback in Visual Basic.

VBScript Example

The following VBScript code defines a callback function, serviceChangeCallback, to be invoked when the values of state variables change or when the service instance becomes unavailable. The function has three arguments.

The first argument to the function specifies the reason the callback is invoked. It is invoked either because a state variable changed, or because the service instance has become unavailable.

The second argument is the Service object for which the callback is invoked. If the callback is being invoked for a state variable change, then the function is passed two additional arguments: the name of the variable that changed, and its new value.

In this example, the callback simply displays a message box that shows the name of the changed variable and its new value, and if the callback was invoked for a state variable change. Otherwise, it displays a message that indicates the service instance is no longer available.

The last part of the code fragment shows how to register the callback function using the AddCallback method. The service object variables, appService and xportService are assumed to have been initialized as shown in Obtaining Service Objects.

'State Change Callback Function

'Note:  In the sub declaration statement below, VARIABLE_UPDATE
'is one of two possible values for the callbackType argument;
'the other is SERVICE_INSTANCE_DIED

Sub serviceChangeCallback(callback type, svcObj, varName, value)
    If (callback type = "VARIABLE_UPDATE") then
        Dim outString
        outString = "State Variable Changed:" & vbCrLf
        outString = outString & varName & " == " & value

        MsgBox(outString, "Service Callback")
    Else
        MsgBox("Service instance is no longer available",
               "Service Callback")
    End If
End Sub

…

'Add our state change callback to each service
appService.AddCallback GetRef("serviceChangeCallback")
xportService.AddCallback GetRef("serviceChangeCallback")

C++ Example

// CSrvCallback class declaration

class ATL_NO_VTABLE CSrvCallback :
    public CComObjectRootEx <CComSingleThreadModel>,
    public IUPnPServiceCallback
{
public:
    CSrvCallback ();

    virtual ~ CSrvCallback ();

    DECLARE_NOT_AGGREGATABLE(CSrvCallback)

    BEGIN_COM_MAP(CSrvCallback)
        COM_INTERFACE_ENTRY(IUPnPServiceCallback)
    END_COM_MAP()

public:

// IUPnPServiceCallback Methods
    STDMETHOD (StateVariableChanged) (
                         IUPnPService    * pus,
                         LPCWSTR         pcwszStateVarName,
                         VARIANT         vaValue);

    STDMETHOD (ServiceInstanceDied) (
                         IUPnPService    * pus);

};

#define MAX_LENGTH 256

// CSrvCallback class implementation

CSrvCallback::CSrvCallback ()
{
}

CSrvCallback::~CSrvCallback ()
{
}

HRESULT
CSrvCallback::StateVariableChanged (
                IUPnPService    * pSrv,
                LPCWSTR         pcwszStateVarName,
                VARIANT         varVal)
{
    HRESULT    hr = S_OK;
    WCHAR      wszVal[MAX_LENGTH + 1];
    BSTR       bstrSTI = NULL;

    switch (varVal.vt)
    {
        case VT_BSTR:
            _snwprintf(wszVal, MAX_LENGTH, L"%s", varVal.bstrVal);
            break;

        case VT_I1:
        case VT_I2:
        case VT_INT:
            _snwprintf(wszVal, MAX_LENGTH, L"%d", varVal.intVal);
            break;

        case VT_BOOL:
            _snwprintf(wszVal, MAX_LENGTH, L"%d", varVal.boolVal);
            break;

        case VT_I4:
            _snwprintf(wszVal, MAX_LENGTH, L"%ld", varVal.lVal);
            break;

        case VT_BOOL:
            _snwprintf(wszVal, MAX_LENGTH, L"%d", varVal.boolVal);
            break;

        case VT_DATE:
            _snwprintf(wszVal, MAX_LENGTH, L"%f", varVal.date);
            break;

        case VT_R8:
            _snwprintf(wszVal, MAX_LENGTH, L"%f", varVal.dblVal);
            break;

        case VT_CY:
            _snwprintf(wszVal, MAX_LENGTH, L"%I64d", varVal. cyVal.int64);
            break;

        default:
             _snwprintf(wszVal, MAX_LENGTH, L"Unknown Value");
             break;

    }
    if(NULL != pSrv)
    {
        hr = pSrv->get_ServiceTypeIdentifier(&bstrSTI);
        if(SUCEEDED(hr))
        {
            wprintf(L"StateVariableChanged called for the %s service \n"
                    L"for %s state variable with the value=%s!\n\n",
                    bstrSTI,
                    pcwszStateVarName,
                    wszVal);
        }
    }
    else
        wcerr << L"Null service object pointer received!\n";

    if(NULL != bstrSTI)
        SysFreeString(bstrSTI);

    return S_OK;

}

HRESULT
CSrvCallback::ServiceInstanceDied(IUPnPService    *pSrv)
{
    HRESULT    hr = S_OK;
    BSTR       bstrSTI = NULL;

    if(NULL != pSrv)
    {
        hr = pSrv->get_ServiceTypeIdentifier(&bstrSTI);
        if(SUCEEDED(hr))
        {
            wprintf(L"ServiceInstanceDied called for the %s service!\n",
                    bstrSTI);
        }
    }

    if(NULL != bstrSTI)
        SysFreeString(bstrSTI);

    return S_OK;
}

// Callback Instantiation

HRESULT
InstantiateCallback(IUnknown** ppCbk)
{
    HRESULT                    hr = S_OK;
    CComObject<CSrvCallback>   *pCbk = NULL;
    IUnknown                   *pUnk = NULL;

    if( (NULL == ppCbk) ||
        IsBadWritePtr(ppCbk, sizeof(IUnknown*) ) )
    {
        hr = E_INVALIDARG;
        wcerr << L"Invalid args received!\n";
        return hr;
    }

    *ppCbk = NULL;
    hr = CComCreator<CComObject <CSrvCallback> >::CreateInstance(
                                                NULL,
                                                IID_IUPnPServiceCallback,
                                                (VOID**)&pCbk);
    if (FAILED(hr))
    {
        wcerr << L"Could not instantiate the callback "
              << L"object - HRESULT 0x"
              << setbase(16)
              << hr << L"\n";
        pCbk = NULL;
        return hr;
    }

    hr = pCbk->QueryInterface(IID_IUnknown, (void**)&pUnk);
    if (FAILED(hr))
    {
        wcerr << L"QueryInterface for IUnknown failed "
              << L" - HRESULT 0x"
              << setbase(16)
              << hr << L"\n";
        pCbk->Release();
        return hr;
    }
    pCbk->Release();

    *ppCbk = pUnk;

    return hr;
}

//
//   Callback Registration code for a previously
//   instantiated pAppService service object pointer
//

    IUnknown    *pCbk = NULL;

    hr = InstantiateCallback(&pCbk);
    if(SUCCEEDED(hr))
    {
        hr = pAppService->AddCallback((IUnknown*)pCbk);
        if(FAILED(hr))
        {
            wcerr << L"AddCallback failed "
                  << L" - HRESULT 0x"
                  << setbase(16)
                  << hr << L"\n";
        }
    }


Querying State Variables

The IUPnPService interface provides the QueryStateVariable method, that returns the value of a specified state variable.

The following examples demonstrate the use of QueryStateVariable to retrieve the value of the Power state variable on a Service object.

VBScript Example

Dim Power

Power = appService.QueryStateVariable("Power")

C++ Example

The following example shows the C++ code required to query the Power variable.

Note The value is returned in a VARIANT structure.

void
QueryPowerVariable(IUPnPService * pService)
{
    HRESULT hr = S_OK;
    BSTR    bstrVarName;
    VARIANT varValue;

    bstrVarName = SysAllocString(L"Power");

    if (bstrVarName)
    {
        hr = pService->QueryStateVariable(bstrVarName,
                                          &varValue);

        if (SUCCEEDED(hr))
        {
            wcout << L"Power == "
                  << V_BOOL(&varValue)
                  << L"\n";

            VariantClear(&varValue);
        }
        else
        {
            wcerr << L"Failed to query state variable – "
                  << L"HRESULT 0x"
                  << setbase(16)
                  << hr << L"\n";
        }
        SysFreeString(bstrVarName);
        bstrVarName = NULL;
    }
    else
    {
        wcerr << L"Failed to allocate variable name string\n";
    }
}


Invoking Actions

The IUPnPService::InvokeAction method allows actions to be invoked on Service objects. This method has two input parameters: the name of an action and an array of input arguments to that action. The parameter has one input/output parameter: an array of output arguments for that action. The method has one output parameter: a return value.

The method causes the action to be invoked on the device. The device generates event notifications if the action causes state variables of the device to change.

VBScript Example

The following VBScript code example invokes two actions on a Service object. The first action, GetTrackInfo, takes one input argument, a track number. The GetTrackInfo action returns the track length as the return value. The action also has one output argument, which contains the track title if the method returns success.

After invoking the GetTrackInfo action, the example invokes the Play action, which takes no arguments. However, because the syntax of InvokeAction requires an array of both input and output arguments, the example must create an empty array, emptyArgs, with no elements. The example passes this array to InvokeAction for both the input and output arguments, along with the name of the action.

'Invoke GetTrackInfo action
Dim args(1)

args(0) = 3

Dim outArgs(1)

Dim returnVal

returnVal = service.InvokeAction("GetTrackInfo", args, outArgs)

'returnVal now contains the track length and outArgs(0) contains
'the track title

'Invoke Play action

Dim emptyArgs(0)

service.InvokeAction "Play", emptyArgs, emptyArgs

C++ Example

The following example defines a C++ function that invokes an action with no arguments. Because InvokeAction requires a SAFEARRAY of arguments to be passed in, this example creates an empty SAFEARRAY. Since this action does not return a value or have output arguments, this example ignores the last two VARIANT values passed to InvokeAction.

The device generates event notifications if the action causes state variables of the device to change.

void
InvokePlay(IUPnPService * pService)
{
    HRESULT hr;
    BSTR bstrActionName;

    bstrActionName = SysAllocString(L"Play");

    if (bstrActionName)
    {
        SAFEARRAYBOUND  rgsaBound[1];
        SAFEARRAY       * psa = NULL;

        rgsaBound[0].lLbound = 0;
        rgsaBound[0].cElements = 0;

        psa = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);

        if (psa)
        {
            LONG    lStatus;
            VARIANT varInArgs;
            VARIANT varOutArgs;
            VARIANT varReturnVal;

            VariantInit(&varInArgs);
            VariantInit(&varOutArgs);
            VariantInit(&varReturnVal);

            varInArgs.vt = VT_VARIANT | VT_ARRAY;

            V_ARRAY(&varInArgs) = psa;

            hr = pService->InvokeAction(bstrActionName,
                                        varInArgs,
                                        &varOutArgs,
                                        &varReturnVal);

            if (SUCCEEDED(hr))
            {
                wcout << L"Action invoked successfully\n";
            }
            else
            {
                wcerr << L"Failed to invoke action - HRESULT 0x"
                      << setbase(16)
                      << hr << L"\n";

            }

            SafeArrayDestroy(psa);
        }
        else
        {
            wcerr << L"Failed to create safe array\n";
        }

        SysFreeString(bstrActionName);
    }
    else
    {
        wcerr << L"Failed to allocate action name string\n";
    }
}

The following example invokes the GetTrackInfo action. It takes a track number as an argument, returns the track length as a return value, and returns the track title in an output argument. The code is similar to the previous example, except that instead of creating an empty SAFEARRAY of input arguments, this example inserts a VARIANT that contains the track number. If InvokeAction returns success, this example examines the return value and the array of output arguments.

void
InvokeGetTrackInfo(IUPnPService * pService)
{
    HRESULT hr;
    BSTR bstrActionName;

    bstrActionName = SysAllocString(L"GetTrackInfo");

    if (bstrActionName)
    {
        SAFEARRAYBOUND  rgsaBound[1];
        SAFEARRAY       * psa = NULL;

        rgsaBound[0].lLbound = 0;
        rgsaBound[0].cElements = 1;

        psa = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);

        if (psa)
        {
            long rgIndices[1];
            VARIANT varTrackNum;

            rgIndices[0] = 0;
            VariantInit(&varTrackNum);

            varTrackNum.vt = VT_I4;
            V_I4(&varTrackNum) = 3;

            hr = SafeArrayPutElement(psa,
                                     rgIndices,
                                     (void *) &varTrackNum);

            VariantClear(&varTrackNum);

            if (SUCCEEDED(hr))
            {
                LONG    lStatus;
                VARIANT varInArgs;
                VARIANT varOutArgs;
                VARIANT varReturnVal;

                VariantInit(&varInArgs);
                VariantInit(&varOutArgs);
                VariantInit(&varReturnVal);

                varInArgs.vt = VT_VARIANT | VT_ARRAY;

                V_ARRAY(&varInArgs) = psa;

                hr = pService->InvokeAction(bstrActionName,
                                            varInArgs,
                                            &varOutArgs,
                                            &varReturnVal);

                if (SUCCEEDED(hr))
                {
                    SAFEARRAY * psaOutArgs = NULL;
                    VARIANT   varTrackTitle;

                    psaOutArgs = V_ARRAY(&varOutArgs);
                    VariantInit(&varTrackTitle);

                    rgIndices[0] = 0;
                    hr = SafeArrayGetElement(psaOutArgs,
                                             rgIndices,
                                             (void *)&varTrackTitle);

                    if (SUCCEEDED(hr))
                    {
                        wcout << L"Action invoked successfully\n"
                              << L"\tTrack Length == "
                              << V_I4(&varReturnVal) << L"\n"
                              << L"\tTrack Title == "
                              << V_BSTR(&varTrackTitle) << L"\n";
                    }
                    else
                    {
                        wcerr << L"Failed to get array element -"
                              << L" HRESULT 0x"
                              << setbase(16)
                              << hr << L"\n";
                    }

                    VariantClear(&varTrackTitle);
                    VariantClear(&varReturnVal);
                    VariantClear(&varOutArgs);
                }
                else
                {
                    wcerr << L"Failed to invoke action - HRESULT 0x"
                          << setbase(16)
                          << hr << L"\n";
                }
            }
            else
            {
                wcerr << L"Failed to insert argument into array - "
                      << L"HRESULT 0x"
                      << setbase(16)
                      << hr << L"\n";
            }

            SafeArrayDestroy(psa);
        }
        else
        {
            wcerr << L"Failed to create safe array\n";
        }

        SysFreeString(bstrActionName);
    }
    else
    {
        wcerr << L"Failed to allocate action name string\n";
    }
}


Using the UPnP Control Point API

This section contains sample code that illustrates how to use the UPnP Control Point API to create applications that control UPnP devices and request services. The following sample code is included:

  • Programming Considerations
  • Searching Asynchronously in C++
  • Registering a callback in Visual Basic
  • Creating a media player Web page


Programming Considerations

Developers who create UPnP applications (or control points) must use these applications from a COINIT_APARTMENTTHREADED client. There are known problems when using the UPnP Control Point API from a COINIT_MULTITHREADED client running under stress.


Searching Asyncronously in C++

Platform SDK: Universal Plug and Play

Searching Asynchronously in C++

This topic provides the necessary information to develop a C++ application that searches for devices asynchronously.

#define TRACE(x) fprintf(stderr, x)
#define TRACEERROR(x, hr) fprintf(stderr, x " failed, hr=%x\n", hr)

HRESULT
HrDisplayDevice(IUPnPDevice * pud)
{
    assert(pud);

    HRESULT hr;

    BSTR bstrUdn;
    BSTR bstrName;

    hr = pud->get_UniqueDeviceName(&bstrUdn);
    if (SUCCEEDED(hr))
    {
        assert(bstrUdn);

        hr = pud->get_FriendlyName(&bstrName);
        if (SUCCEEDED(hr))
        {
            assert(bstrName);
            printf("found: name=%ls, udn: %ls\n", bstrName, bstrUdn);

            ::SysFreeString(bstrName);
        }
        else
        {
            TRACEERROR("HrDisplayDevice: get_FriendlyName", hr);
        }

        ::SysFreeString(bstrUdn);
    }
    else
    {
        TRACEERROR("HrDisplayDevice: get_UniqueDeviceName", hr);
    }

    return hr;
}

class CDeviceFinderCallback :public IUPnPDeviceFinderCallback
{
public:
    CDeviceFinderCallback()
    {
        m_ulRef = 0;
        m_hSearchComplete = INVALID_HANDLE_VALUE;
    }

    ~CDeviceFinderCallback()
    {
        assert(0 == m_ulRef);

        if (INVALID_HANDLE_VALUE != m_hSearchComplete)
        {
            assert(m_hSearchComplete);

            BOOL fResult;

            fResult = ::CloseHandle(m_hSearchComplete);
            assert(fResult);
        }
    }

    HRESULT HrInit(HANDLE hSearchComplete)
    {
        assert(hSearchComplete);
        assert(INVALID_HANDLE_VALUE != hSearchComplete);

        HRESULT hr;

        hr = S_OK;

        {
            HANDLE hProcess;
            BOOL fResult;

            hProcess = ::GetCurrentProcess();

            // note: The client can only signal the event with this
            // handle, not wait on it.  This is fine, since the client
            // only needs to signal it.

            fResult = ::DuplicateHandle(hProcess,
                                        hSearchComplete,
                                        hProcess,
                                        &m_hSearchComplete,
                                        EVENT_MODIFY_STATE,
                                        FALSE,
                                        0);
            if (!fResult)
            {
                hr = HRESULT_FROM_WIN32(GetLastError());
                TRACEERROR("CDeviceFinderCallback::HrInit: DuplicateHandle", hr);

                m_hSearchComplete = INVALID_HANDLE_VALUE;

                goto Cleanup;
            }

            // note: no need to close hndProcess
        }

        // note: if you add code here, you must add code at Cleanup to
        // clean up the handle duplicated above

    Cleanup:
        return hr;
    }

    // IUPnPDeviceFinderCallback methods

    STDMETHOD(QueryInterface)(/* [in] */  REFIID iid,
                              /* [out] */ LPVOID * ppvObject)
    {
        HRESULT hr;
        VOID * pvResult;

        if (!ppvObject)
        {
            return E_INVALIDARG;
        }

        hr = E_NOINTERFACE;
        pvResult = NULL;

        if (IsEqualIID(iid, IID_IUnknown))
        {
            pvResult = reinterpret_cast<IUPnPDeviceFinderCallback*>(this);
        }
        else if (IsEqualIID(iid, IID_IUPnPDeviceFinderCallback))
        {
            pvResult = reinterpret_cast<IUnknown*>(this);
        }

        if (pvResult)
        {
            hr = S_OK;
            AddRef();
        }

        *ppvObject = pvResult;
        return hr;
    }

    ULONG STDMETHODCALLTYPE AddRef()
    {
        return ++m_ulRef;
    }

    ULONG STDMETHODCALLTYPE Release()
    {
        ULONG ulRef;

        ulRef = --m_ulRef;
        if (!ulRef)
        {
            delete this;
        }

        return ulRef;
    }

    STDMETHOD(DeviceAdded)  (/* [in] */ LONG lFindData,
                             /* [in] */ IUPnPDevice * pDevice)
    {
        HRESULT hr = E_INVALIDARG;

        if (pDevice)
        {
            hr = HrDisplayDevice(pDevice);
        }

        return hr;
    }

    STDMETHOD(DeviceRemoved)(/* [in] */ LONG lFindData,
        /* [in] */ BSTR bstrUDN)
    {
        HRESULT hr = E_INVALIDARG;

        if (bstrUDN)
        {
            hr = S_OK;
            printf("gone: %ls\n", bstrUDN);
        }

        return hr;
    }

    STDMETHOD(SearchComplete)(/* [in] */ LONG lFindData)
    {
        assert(INVALID_HANDLE_VALUE != m_hSearchComplete);

        HRESULT hr;
        BOOL fResult;

        hr = S_OK;

        fResult = ::SetEvent(m_hSearchComplete);
        if (!fResult)
        {
            // the call to SetEvent failed.
            hr = HRESULT_FROM_WIN32(GetLastError());

            TRACEERROR("CDeviceFinderCallback::SearchComplete: SetEvent", hr);
        }

        return hr;
    }

private:
    ULONG m_ulRef;
    HANDLE m_hSearchComplete;
};

HRESULT
HrFindAsync(IUPnPDeviceFinder * pdf, LPCWSTR pszSearchString)
{
    assert(pdf);
    assert(pszSearchString);

    // 1. Create an event to signal when the search is complete
    // 2. Start the search, and pump messages while waiting on the
    // event

   CONST DWORD dwSearchTimeout = 4000;     // Wait 4 sec after search
                                           // completes for new device
                                           // notifications

    HRESULT hr;
    CDeviceFinderCallback * pdfc;
    HANDLE hndDoneEvent;
    BOOL fSearchDone;
    LONG lFindData;

    hr = S_OK;

    pdfc = NULL;
    hndDoneEvent = INVALID_HANDLE_VALUE;

    hndDoneEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!hndDoneEvent)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        TRACEERROR("HrFindAsync: CreateEvent", hr);

        goto Cleanup;
    }

    pdfc = new CDeviceFinderCallback();
    if (!pdfc)
    {
        hr = E_OUTOFMEMORY;
        goto Cleanup;
    }

    pdfc->AddRef();

    hr = pdfc->HrInit(hndDoneEvent);

    if (FAILED(hr))
    {
        goto Cleanup;
    }

    fSearchDone = FALSE;

    {
        BSTR bstrSearchString;
        IUnknown * punkCallback;

        bstrSearchString = ::SysAllocString(pszSearchString);
        if (!bstrSearchString)
        {
            hr = E_OUTOFMEMORY;
            goto Cleanup;
        }

        punkCallback = dynamic_cast<IUnknown *>(pdfc);

        hr = pdf->CreateAsyncFind(bstrSearchString, 0, punkCallback, &lFindData);

        ::SysFreeString(bstrSearchString);

        if (FAILED(hr))
        {
            TRACEERROR("HrFindAsync: CreateAsyncFind", hr);

            goto Cleanup;
        }
    }

    hr = pdf->StartAsyncFind(lFindData);
    if (FAILED(hr))
   {
        TRACEERROR("HrFindAsync: StartAsyncFind", hr);

        goto Cleanup;
    }

    while (TRUE)
    {
        CONST DWORD cdwMessageSignal = WAIT_OBJECT_0 + 1;
        DWORD dwSignaled;

        dwSignaled = ::MsgWaitForMultipleObjectsEx(1,
                                                   &hndDoneEvent,
                                                   dwSearchTimeout,
                                                   QS_ALLINPUT,
                                                   MWMO_INPUTAVAILABLE);
        if (WAIT_TIMEOUT == dwSignaled)
        {
            if (fSearchDone)
            {
                printf("done.\n");
                break;
            }

            // Otherwise, client timed out before the search
            // completed.  Since the search is still going on,
            // wait a bit longer.
        }
        else if (dwSignaled == WAIT_OBJECT_0)
        {
            // The search has completed.

            printf("search complete, looking for new devices...\n");

            assert(!fSearchDone);
            fSearchDone = TRUE;
        }
        else if (cdwMessageSignal == dwSignaled)
        {
            MSG msg;

            // There is a window message available: dispatch it.

            while (PeekMessage(&msg,
                               NULL,
                               NULL,
                               NULL,
                               PM_REMOVE))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
        }
        else
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
            TRACEERROR("HrFindAsync: MsgWaitForMultipleObjectsEx", hr);

            break;
        }
    }

    hr = pdf->CancelAsyncFind(lFindData);
    if (FAILED(hr))
    {
        TRACEERROR("HrFindAsync: CancelAsyncFind", hr);

        goto Cleanup;
    }

Cleanup:
    if (INVALID_HANDLE_VALUE != hndDoneEvent)
    {
        ::CloseHandle(hndDoneEvent);
    }

    if (pdfc)
    {
        pdfc->Release();
    }

    return S_OK;
}


Registering a Callback in Visual Basic

Adding a callback in Visual Basic is different from the method used in VBScript. The GetRef() function used in VBScript is different than the one used in Visual Basic. Therefore, a developer must create an IDispatch object that has the callback function as the default method. This topic provides the necessary information to develop Visual Basic applications.

To implement this callback in an application

  1. Add references to two object libraries: TLBTypes.olb and VboostTypes6.olb. These object libraries are provided with the UPnP Control Point sample code.
  2. Add a reference to Cbklib.tlb. This file defines the structure of the callback function.

    The cbklib.tlb is created using the cbklib.odl file that is included as part of the UPnP Control Point sample code. It is recommended that the name of this file change for callback functions that differ in the structure of their parameters. This example uses mktyplib to create the type library file.

  3. Write the callback function. The parameters are the same as in the VBScript example in Registering a Callback. This example prints a string whenever an event arrives.
    Function eventHandler(ByVal callbackType As Variant, _
ByVal svcObj As Variant, ByVal varName As Variant, _
ByVal value As Variant) As Long

    On Error GoTo Error

    MsgBox "Event Handler Called"
Exit Function

Error:
    With Err
        If .Number > 0 Then
            eventHandler = .Number Or &H800A0000
        Else
            eventHandler = .Number
        End If
    End With
End Function
  4. Add the callback function to the IUPnPService object, as shown in the following example, or in another object such as IUPnPDeviceFinder, using the appropriate callback type library (cbklib.tbl).
    Public Sub AddCbFunction(upnpSvc As UPnPService)

Dim X As CallbackIUnknownLib.CallBackInterface
Dim obj As Object
Dim ptinfo As ITypeInfo
Dim ptcomp As ITypeComp

    With LoadTypeLibEx(App.Path & "\cbklib.tlb", _
      REGKIND_NONE).GetTypeComp
        .BindType "CallBackInterface", 0, ptinfo, ptcomp
    End With

    'NewDelegator is defined in FunctionDelegator.bas
    Set X = NewDelegator(AddressOf eventHandler)
    Set obj = CreateStdDispatch(Nothing, ObjPtr(X), ptinfo)
    upnpSvc.AddCallback obj
End Sub

In the following example, the IUPnPService object is passed to the function. The callback function is then added as the parameter.

Dim device as UPnPDevice
Dim svcObj as UpnPService

' Initialize the device using the FindByType or using other methods of finding the devices
    Set svcObj = device.Services("appropriateService")
    Call AddCbFunction(svcObj)

Object Libraries Used in the Sample Code

The previous examples and the UPnP Control Point sample code use some of the following object libraries:

  1. TLBTypes.olb — This library defines some of the type library types and interfaces that are used in the sample code. It defines some of the functions, such as LoadTypeLibEx, that are available in C or C++ to be used in VB.
  2. VboostTypes6.olb — This library defines some base types which are used in TLBTypes.olb and FunctionDelegator.bas. Further information regarding TLBTypes can be found in the book Advanced Visual Basic 6: Power Techniques for Everyday Programs, by Matthew Curland (Addison-Wesley, July 2000, ISBN: 0-201-70712-8)

The UPnP Control Point sample code and the following libraries are related to this section and are needed to implement this callback. They can be found with the UPnP Control Point sample code:

  • Cbklib.odl
  • Cbklib.tlb
  • VboostTypes6.olb
  • TLBTypes.olb
  • FunctionDelegator.bas


Creating a Media Player Web Page

The sample code in this section uses the UPnP Control Point API to create a simple web page to control UPnP media player devices. The web page is shown in the following illustration.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>

<HEAD>
<TITLE>Presentation page for an emulated UPnP midi player
     device</TITLE>
</HEAD>

<BODY>

<BR>
'Set up the controls
Open media file: <INPUT type="TEXT" value="c:\travels.mid"
     ID="FileName" NAME="FileName" SIZE="50,5" MAXLENGTH="250">
<BR>
<BR>

<INPUT type="button" ID="PlayButton" onclick="OnPlay()"
     value="Play >>">
<INPUT type="button" ID="PauseButton" onclick="OnPause(this)"
     value="Pause">
<INPUT type="button" ID="StopButton" onclick="OnStop()" value="Stop">
<INPUT type="button" ID="VolUpButton" onclick="OnVolumeUp()"
     value="VolumeUp">
<INPUT type="button" ID="VolDownButton" onclick="OnVolumeDown()"
     value="VolumeDown">

<H3>App State</H3>

'Set up the table that displays state information
<TABLE BGCOLOR='#D6D7DE' BORDER=0 VALIGN=top ALIGN=left CELLPADDING=1
     CELLSPACING=3 height="157">

  <TR>
    <TD BGCOLOR='#000000' VALIGN=center ALIGN=center WIDTH=60
         height="17"><B><FONT SIZE="2"
         COLOR=whitesmoke>Variable</FONT></B></TD>
    <TD VALIGN=middle ALIGN=left BGCOLOR='#000000' WIDTH=470
         height="17"><B><FONT SIZE="2"
         COLOR=whitesmoke>&nbsp;&nbsp;Value</FONT></B></TD>
  </TR>

  <TR>
    <TD BGCOLOR="#FFFFFF" VALIGN=center ALIGN=center
         height="59">File</TD>
    <TD BGCOLOR="#FFFFFF" valign="top" height="59">&nbsp;&nbsp;<P
         ID=MyFile></P></TD>
  </TR>

  <TR>
    <TD  BGCOLOR="#FFFFFF" VALIGN=center ALIGN=center
         height="59">Volume</TD>
    <TD  BGCOLOR="#FFFFFF" valign="top" height="59">&nbsp;&nbsp;<P
         ID=Volume></P></TD>
  </TR>

</TABLE>

<SCRIPT language=VBScript>

'Unique Device Name (UUID)
MediaPlayerUDN = "uuid:schemas-upnp-org:device:mediaplayer.v1.00.00:[42237E7A-2C00-41cd-9CAE-E59BF82AA259]"

'Initialize the set of services offered by the device, and other
'variables
Dim appService
Dim xportService
Dim Vol(1)
Dim args(0)
Dim File(1)
Dim bPlaying
Dim bPaused

set appService=Nothing
set xportService=Nothing
bPlaying = False
bPaused = False

'Create the device finder object
Dim descriptionDoc
Set descriptionDoc = CreateObject("UPnP.DescriptionDocument")

'Load the description doc for the device
descriptionDoc.Load("./description.xml")

device = descriptionDoc.RootDevice

'Connect to the device's DVDVideo and AVTTransport services
set xportService = device.Services("urn:upnp-org:serviceId:DVDVideo")
set appService = device.Services("urn:upnp-org:serviceId:AVTransport")

appService.AddCallback GetRef("eventHandler")

' initialize the volume
Dim outArgs (0)

Vol(0) = 3
appService.InvokeAction "SetVolume", Vol, outArgs

'Event handler for the appService
'Update the state table maintained locally
Sub eventHandler(callbackType, svcObj, varName, value)
  If (callbackType = "VARIABLE_UPDATE") Then
       select case svcObj.Id
            case "upnp:id:mediaapp"
                 select case varName
                      Case "File" MyFile.innerText = value
                                  FileName.value = value
                      Case "Volume" Volume.innerText = value
                 end select
       end select
    End If
End Sub

'Invoke the play action
function OnPlay ()
  File(0) = FileName.value
  Dim outArgs(0)

  If File(0) = "" Then
       alert("Please enter the path to the file to play!")
  Else
       appService.InvokeAction "Power", args, outArgs
       appService.InvokeAction "LoadFile", File, outArgs
       xportService.InvokeAction "Play", args, outArgs

       bPlaying = True
  End if
end function

'Invoke the Pause action
function OnPause (button)
Dim outArgs (0)

  If bPlaying Then
       xportService.InvokeAction "Pause", args, outArgs
       bPaused = True
       bPlaying = False
  ElseIf bPaused Then
       xportService.InvokeAction "Play", args, outArgs
       bPaused = False
       bPlaying = True
  End if

  If bPaused Then
       button.value="Resume"
  Else
       button.value="Pause"
  End if
end function

'Invoke the Stop action
function OnStop ()
Dim outArgs (0)

  xportService.InvokeAction "Stop", args, outArgs
  bPlaying = False
end function

'Invoke the VolumeUp action
function OnVolumeUp ()
Dim outArgs (0)

  appService.InvokeAction "VolumeUp", args, outArgs
end function

'Invoke the VolumeDown action
function OnVolumeDown ()
Dim outArgs (0)

  appService.InvokeAction "VolumeDown", args, outArgs
end function

</SCRIPT>

</BODY>

</HTML>


UPnP Control Point API Reference

The following interfaces are part of the Universal Plug and Play Control Point API (UPnP). The UPnP Control Point API supports Microsoft® Visual Basic® Scripting Edition (VBScript), Microsoft Visual Basic® (VB), and C++.

Interface | Description
IUPnPDescriptionDocument | Enables an application to load a device description.
IUPnPDescriptionDocumentCallback | Enables an application to receive the results of an asynchronous load operation.
IUPnPDevice | Enables an application to retrieve information about a specific device.
IUPnPDeviceFinder | Enables an application to find a device.
IUPnPDeviceFinderCallback | Enables an application to receive asynchronous search results from UPnP.
IUPnPDevices | Enumerates a collection of devices.
IUPnPService | Enables an application to retrieve state information and invoke actions for a service.
IUPnPServiceCallback | Enables an application to receive notification from UPnP when events occur.
IUPnPServices | Enumerates a collection of services.


IUPnPDescriptionDocument

The IUPnPDescriptionDocument interface enables an application to load and unload a device description.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

You should use this interface when creating a Web page that runs from a device.

Methods and Properties in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
ReadyState | Property that returns the status of the document load operation.
Load | Method that loads a document synchronously.
LoadAsync | Method that loads a document asynchronously.
LoadResult | Property that returns the success or failure code of a completed load operation.
Abort | Method that stops an asynchronous load operation.
RootDevice | Method that returns the root device of the loaded document's device tree.
DeviceByUDN | Method that returns a device with the specified unique device name (UDN).

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPDescriptionDocument::Abort

The IUPnPDescriptionDocument::Abort method stops an asynchronous load operation started by IUPnPDescriptionDocument::LoadAsync.

HRESULT Abort(void);

Parameters

This method has no parameters.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDescriptionDocument::LoadAsync


IUPnPDescriptionDocument::DeviceByUDN

The IUPnPDescriptionDocument::DeviceByUDN method returns the device with the specified unique device name (UDN) contained within the loaded description document.

HRESULT DeviceByUDN(
  BSTR bstrUDN,
  IUPnPDevice **ppudDevice
);

Parameters

bstrUDN
[in] Specifies the UDN of the device.
ppudDevice
[out] Receives a reference to an IUPnPDevice object that describes the device. This reference must be released when it is no longer needed.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

Do not use IUPnPDescriptionDocument::DeviceByUDN unless a device description is first loaded using either IUPnPDescriptionDocument::Load or IUPnPDescriptionDocument::LoadAsync. The search operation only searches in the currently loaded device description.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDevice


IUPnPDescriptionDocument::Load

The IUPnPDescriptionDocument::Load method loads a document synchronously. This method does not return control to the caller until the load operation is complete.

HRESULT Load(
  BSTR bstrUrl
);

Parameters

bstrUrl
[in] Specifies the URL of the document to load.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h, or one of the following UPnP return values.

UPnP-specific Return value | Description
UPNP_E_DEVICE_ELEMENT_EXPECTED | XML document does not have a device element. It is missing either from the root element or the DeviceList element.
UPNP_E_DEVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Device element.
UPNP_E_ICON_ELEMENT_EXPECTED | XML document does not have an icon element. It is missing from the IconList element, or the DeviceList element does not contain a IconList element.
UPNP_E_ICON_NODE_INCOMPLETE | XML document is missing one of the required elements from the Icon element.
UPNP_E_ROOT_ELEMENT_EXPECTED | XML document does not have a root element at the top level of the document.
UPNP_E_SERVICE_ELEMENT_EXPECTED | XML document does not have a service element. It is missing from the ServiceList element, or the DeviceList element does not contain a ServiceList element.
UPNP_E_SERVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Service element.

Remarks

This method should not be called from a user interface thread.

If the IUPnPDescriptionDocument::Load method is called by a script within a Web page, bstrUrl may be a relative URL. The address of the current web page is used as the base URL.

If this method is called from a Web page, the URL the caller specifies must refer to the same server from which the Web page was loaded.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDescriptionDocument::LoadAsync


IUPnPDescriptionDocument::LoadAsync

The IUPnPDescriptionDocument::LoadAsync method loads a document asynchronously. This method returns control to the caller immediately, and uses the specified callback to notify the caller when the operation is complete.

HRESULT LoadAsync(
  BSTR bstrUrl,
  IUnknown *punkCallback
);

Parameters

bstrUrl
[in] Specifies the URL of the document to load. If the URL specified is a relative URL, the server name is prepended to the value of bstrUrl.
punkCallback
[in] Reference to an IUnknown that specifies the callback UPnP uses to notify the caller when the operation is complete. If the load operation did not fail immediately, this callback indicates whether or not the load operation succeeded or failed.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h, or one of the following UPnP return values.

UPnP-specific Return value | Description
UPNP_E_DEVICE_ELEMENT_EXPECTED | XML document does not have a device element It is missing either from the root element or the DeviceList element.
UPNP_E_DEVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Device element.
UPNP_E_ICON_ELEMENT_EXPECTED | XML document does not have an icon element. It is missing from the IconList element, or the DeviceList element does not contain a IconList element.
UPNP_E_ICON_NODE_INCOMPLETE | XML document is missing one of the required elements from the Icon element.
UPNP_E_ROOT_ELEMENT_EXPECTED | XML document does not have a root element at the top level of the document.
UPNP_E_SERVICE_ELEMENT_EXPECTED | XML document does not have a service element. It is missing from the ServiceList element, or the DeviceList element does not contain a ServiceList element.
UPNP_E_SERVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Service element.

Remarks

This method should not be called from a user interface thread.

If the IUPnPDescriptionDocument::Load method is called by a script within a Web page, bstrUrl may be a relative URL. The address of the current web page is used as the base URL.

If this method is called from a Web page, the URL the caller specifies must refer to the same server from which the Web page was loaded.

The object referred to by pUnkCallback must either support the IUPnPDescriptionDocumentCallback interface, or the IDispatch interface. The IUPnPDescriptionDocument::LoadAsync method first queries pUnkCallback for the IUPnPDescriptionDocumentCallback interface. If this interface is not supported, the IUPnPDescriptionDocument::LoadAsync method then queries pUnkCallback for the IDispatch interface. If the IDispatch interface is not supported, both checks have failed and The IUPnPDescriptionDocument::LoadAsync method returns E_FAIL.

If only IDispatch is supported, the Service object invokes the callback by calling IDispatch::Invoke with the dispatch ID specified as zero, which indicates the default method. This default IDispatch method is passed the same parameters as the IUPnPDescriptionDocumentCallback method, but the first parameter passed is a string that indicates the reason the callback is invoked. Valid values are VARIABLE_UPDATE and SERVICE_INSTANCE_DIED.

The callback based on IDispatch for the IUPnPDescriptionDocument::LoadAsync method works as a script function that takes one parameter. This parameter is the result of the load operation. If the parameter is zero, the load succeeded, and the user can retrieve device objects from the document. If the parameter is non-zero, it describes the error. The value is the same as the error code that the IUPnPDescriptionDocument::Load method returns.

In Visual Basic® Scripting Edition (VBScript) development software, the second argument must be GetRef(funcname), where funcname is the name of the callback subroutine.

If this function returns S_OK, IUPnPDescriptionDocumentCallback::LoadComplete is invoked by UPnP.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDescriptionDocument::Load


IUPnPDescriptionDocument::LoadResult

The IUPnPDescriptionDocument::LoadResult property returns the success or failure code of a completed load operation.

HRESULT LoadResult(
  long *phrError
);

Parameters

phrError
[out] Receives a reference to the success or failure code.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method returns to the caller the error that the IUPnPDescriptionDocument::Load or IUPnPDescriptionDocument::LoadAsync method does. This method can be used when it is necessary to separate the load operation from the error checking.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDescriptionDocument::Load, IUPnPDescriptionDocument::LoadAsync


IUPnPDescriptionDocument::ReadyState

The IUPnPDescriptionDocument::ReadyState property returns the status of the document load operation. This status indicates the state of the Load or LoadAsync method. These states are the standard ready-state values.

HRESULT ReadyState(
  LONG *plReadyState
);

Parameters

plReadyState
[out] Receives a reference to the ready state.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument


IUPnPDescriptionDocument::RootDevice

The IUPnPDescriptionDocument::RootDevice method returns the root device of the currently loaded document's device tree.

HRESULT RootDevice(
  IUPnPDevice **ppudRootDevice
);

Parameters

ppudRootDevice
[out] Receives a reference to an IUPnPDevice object that describes the device. This reference must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method can be used for similar devices that have different UDNs. Use this method to create generic applications.

Do not use IUPnPDescriptionDocument::RootDevice unless a device description is first loaded using either IUPnPDescriptionDocument::Load or IUPnPDescriptionDocument::LoadAsync. The search operation only searches in the currently loaded device description.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDevice


IUPnPDescriptionDocumentCallback

The IUPnPDescriptionDocumentCallback interface allows UPnP to communicate the results of an asynchronous load operation to an application.

When to Implement

Developers should implement this interface for C++ applications that are written using the asynchronous load methods of the IUPnPDescriptionDocument interface. Developers using all other programming languages, such as Visual Basic® development system, should implement a custom callback function to receive callbacks.

When to Use

UPnP uses this callback when the load operation is completed.

Methods and Properties in Vtable Order

IUnknown Methods

Method | Description
LoadComplete | Indicates that a load operation is completed.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: upnp.idl.
Library: Included as a resource in upnp.dll.


IUPnPDescriptionDocumentCallback::LoadComplete

The IUPnPDescriptionDocumentCallback::LoadComplete method is invoked when UPnP has finished loading a device description.

HRESULT LoadComplete(
  HRESULT hrLoadResult
);

Parameters

hrLoadResult
[in] Specifies the load operation UPnP has completed. Possible return values are:
UPnP-specific Return value | Description
UPNP_E_DEVICE_ELEMENT_EXPECTED | XML document does not have a device element. It is missing either from the root element or the DeviceList element.
UPNP_E_DEVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Device element.
UPNP_E_ICON_ELEMENT_EXPECTED | XML document does not have an icon element. It is missing from the IconList element, or the DeviceList element does not contain a IconList element.
UPNP_E_ICON_NODE_INCOMPLETE | XML document is missing one of the required elements from the Icon element.
UPNP_E_ROOT_ELEMENT_EXPECTED | XML document does not have a root element at the top level of the document.
UPNP_E_SERVICE_ELEMENT_EXPECTED | XML document does not have a service element. It is missing from the ServiceList element, or the DeviceList element does not contain a ServiceList element.
UPNP_E_SERVICE_NODE_INCOMPLETE | XML document is missing one of the required elements from the Service element.

Return Values

UPnP does not expect the application to return a specific value; any value returned is ignored by UPnP.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: upnp.idl.
Library: Included as a resource in upnp.dll.

See Also

IUPnPDescriptionDocument, IUPnPDescriptionDocument::LoadAsync


IUPnPDevice

The IUPnPDevice interface enables an application to retrieve information about a specific device.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

The interface is used when you need to access the basic properties and services of a device.

Methods and Properties in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
IsRootDevice | Property that indicates whether the device is the topmost device in the device tree.
RootDevice | Property that returns the topmost device in the device tree.
ParentDevice | Property that returns the parent of the device.
HasChildren | Property that indicates whether the device has any child devices.
Children | Property that returns the child devices of the device.
UniqueDeviceName | Property that returns the unique device name (UDN) of the device.
FriendlyName | Property that returns the device display name.
Type | Property that returns the device type uniform resource identifier (URI).
PresentationURL | Property that returns the presentation URL for a Web page that can be used to control the device.
ManufacturerName | Property that returns a human-readable form of the manufacturer name.
ManufacturerURL | Property that returns the URL for the manufacturer's Web site.
ModelName | Property that returns a human-readable form of the model name.
ModelNumber | Property that returns a human-readable form of the model number.
Description | Property that returns a human-readable form of the summary of a device's functionality.
ModelURL | Property that returns the URL for a Web page that contains model-specific information.
UPC | Property that returns a human-readable form of the product code.
SerialNumber | Property that returns a human-readable form of the serial number.
IconURL | Method that returns a URL from which an icon of the specified format can be loaded.
Services | Property that returns the list of services provided by the device.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPDevice::Children

The IUPnPDevice::Children property returns all the child devices of the device. The devices are returned in an IUPnPDevices collection.

HRESULT Children(
  IUPnPDevices **ppudChildren
);

Parameters

ppudChildren
[out] Receives a reference to an IUPnPDevices collection that enumerates the child devices of the device. This reference must be released when it is no longer required.

If the device has no child devices, the collection object has a length of zero.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

To determine if a device has any children without using IUPnPDevice::Children, use IUPnPDevice::HasChildren.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::HasChildren, IUPnPDevices


IUPnPDevice::Description

The IUPnPDevice::Description property returns a human-readable summary of the device's functionality.

HRESULT Description(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains a short description of the intended functionality of devices of this type. This string must be released when it is no longer required. If the device does not specify a description, this parameter is set to NULL.

Return Values

If the method succeeds, the return value is S_OK. If the device does not specify this URL, the return value is S_FALSE and pbstr is NULL. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice


IUPnPDevice::FriendlyName

The IUPnPDevice::FriendlyName property returns the device display name for the device.

HRESULT FriendlyName(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the device display name. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

It is possible for multiple devices to have the same display name. To determine if two device objects describe the same device, use the unique device name. For more information, see UniqueDeviceName.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, UniqueDeviceName


IUPnPDevice::HasChildren

The IUPnPDevice::HasChildren property returns a flag that specifies whether the device has any child devices. However, the number of child devices is not returned.

HRESULT HasChildren(
  VARIANT_BOOL *pvarb
);

Parameters

pvarb
[out] Receives a reference to a VARIANT_BOOL that contains the value VARIANT_TRUE if the device has one or more child devices; otherwise, it contains the value VARIANT_FALSE.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

Use this method to determine whether or not the application should call IUPnPDevice::Children.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::Children


IUPnPDevice::IconURL

The IUPnPDevice::IconURL method returns a URL from which an icon of the specified format can be loaded.

HRESULT IconURL(
  BSTR bstrEncodingFormat,
  LONG lSizeX,
  LONG lSizeY,
  LONG lBitDepth,
  BSTR *pbstrIconURL
);

Parameters

bstrEncodingFormat
[in] Specifies the MIME type of the encoding format that is requested for the icon.
lSizeX
[in] Specifies the width of the icon, in pixels. Standard values are 16, 32, or 48.
lSizeY
[in] Specifies the height of the icon, in pixels. Standard values are 16, 32, or 48 pixels.
lBitDepth
[in] Specifies the bit depth of the icon. Standard values are 8, 16, or 24.
pbstrIconURL
[out] Receives a reference to a string that contains the URL from which the icon is to be loaded. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

An application can specify any values for lSizeX, lSizeY, and lBitDepth. However, there is no guarantee that an icon exists with those specifications.

If a matching icon does not exist, the URL for the icon that most closely matches the size and bit depth specified is returned.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice


IUPnPDevice::IsRootDevice

The IUPnPDevice::IsRootDevice property is used to determine if the device is the topmost device in the device tree.

HRESULT IsRootDevice(
  VARIANT_BOOL *pvarb
);

Parameters

pvarb
[out] Receives a reference to a VARIANT_BOOL that contains the value VARIANT_TRUE if the device is the topmost device in the device tree; otherwise, it contains the value VARIANT_FALSE.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::Children, IUPnPDevice::RootDevice


IUPnPDevice::ManufacturerName

The IUPnPDevice::ManufacturerName property returns a human-readable form of the manufacturer name of the device.

HRESULT ManufacturerName(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the manufacturer's name. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::ManufacturerURL


IUPnPDevice::ManufacturerURL

The IUPnPDevice::ManufacturerURL property returns the URL for the manufacturer's Web site.

HRESULT ManufacturerURL(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the URL. This string must be released when it is no longer required. If the device does not specify this URL, this parameter is set to NULL.

Return Values

If the method succeeds, the return value is S_OK. If the device does not specify this URL, the return value is S_FALSE and pbstr is NULL. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::ManufacturerName


IUPnPDevice::ModelName

The IUPnPDevice::ModelName property returns a human-readable form of the model name of the device.

HRESULT ModelName(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the model name. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::ModelNumber, IUPnPDevice::ModelURL


IUPnPDevice::ModelNumber

The IUPnPDevice::ModelNumber property returns a human-readable form of the model number of the device.

HRESULT ModelNumber(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the model number. This string must be released when it is no longer required. If the device does not specify a model number, this parameter is set to NULL.

Return Values

If the method succeeds, the return value is S_OK. If the device does not specify a model number, the return value is S_FALSE and pbstr is NULL. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::ModelName, IUPnPDevice::ModelURL


IUPnPDevice::ModelURL

The IUPnPDevice::ModelURL property returns the URL for a Web page that contains model-specific information for the device.

HRESULT ModelURL(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the URL. This string must be released when it is no longer required. If the device does not specify this URL, this parameter is set to NULL.

Return Values

If the method succeeds, the return value is S_OK. If the device does not specify this URL, the return value is S_FALSE and pbstr is NULL. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::ModelName, IUPnPDevice::ModelNumber


IUPnPDevice::ParentDevice

The IUPnPDevice::ParentDevice property returns the parent of the device.

HRESULT ParentDevice(
  IUPnPDevice **ppudDeviceParent
);

Parameters

ppudDeviceParent
[out] Receives a reference to an IUPnPDevice object that describes the parent device. This reference must be released when it is no longer required. If the device has no parent, it is a topmost device, and the parameter receives NULL.

Return Values

If the method succeeds, the return value is S_OK. If the device is a topmost device, the return value is S_FALSE. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

To determine if the device has no parent, use IUPnPDevice::IsRootDevice.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::Children


IUPnPDevice::PresentationURL

The IUPnPDevice::PresentationURL property returns the presentation URL for a Web page that controls the device.

HRESULT PresentationURL(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the presentation URL for the Web page. This string must be released when it is no longer needed. If the device does not specify a presentation URL, this parameter receives an empty string.

Return Values

If the method succeeds, the return value is S_OK. If the device did not specify a presentation URL, the return value is S_FALSE. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice


IUPnPDevice::RootDevice

The IUPnPDevice::RootDevice property returns the topmost device in the device tree. The root device represents a physical object.

HRESULT RootDevice(
  IUPnPDevice **ppudRootDevice
);

Parameters

ppudRootDevice
[out] Receives a reference to an IUPnPDevice object that describes the root device. This reference must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::IsRootDevice


IUPnPDevice::SerialNumber

The IUPnPDevice::SerialNumber property returns a human-readable form of the serial number of the device.

HRESULT SerialNumber(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the serial number. This string must be released when it is no longer needed. If the device does not specify a serial number, this parameter receives an empty string.

Return Values

If the method succeeds, the return value is S_OK. If the device did not specify a serial number, the return value is S_FALSE. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

It is possible for multiple devices to have the same serial number. To determine if two device objects describe the same device, use the unique device name. For more information, see UniqueDeviceName.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::UniqueDeviceName


IUPnPDevice::Services

The IUPnPDevice::Services property returns the list of services provided by the device.

HRESULT Services(
  IUPnPServices **ppusServices
);

Parameters

ppusServices
[out] Receives a reference to an IUPnPServices collection that enumerates the services provided by the device. This reference must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPServices


IUPnPDevice::Type

The IUPnPDevice::Type method returns the uniform resource identifier (URI) of the device type for the device.

HRESULT Type(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the device type's URI. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice


IUPnPDevice::UniqueDeviceName

The IUPnPDevice::UniqueDeviceName property returns the unique device name (UDN) of the device. A UDN is unique; no two devices can have the same UDN.

HRESULT UniqueDeviceName(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the UDN of the device. This string must be released when it is no longer required.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice


IUPnPDevice::UPC

The IUPnPDevice::UPC property returns a human-readable form of the product code.

HRESULT UPC(
  BSTR *pbstr
);

Parameters

pbstr
[out] Receives a reference to a string that contains the product code. This string must be released when it is no longer required. If the device does not specify a product code, this parameter receives an empty string.

Return Values

If the method succeeds, the return value is S_OK. If the device did not specify a product code, the return value is S_FALSE. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This property is optional and can return NULL.

It is possible for multiple devices to have the same product code. To determine if two device objects describe the same device, use the unique device name. For more information, see UniqueDeviceName.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevice, IUPnPDevice::UniqueDeviceName


IUPnPDeviceFinder

The IUPnPDeviceFinder interface enables an application to find a device.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

Use this interface when an application needs the location of a specific device it needs to control.

This interface can be called from within a web page.

Methods and Properties in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
FindByType | Method that searches for devices by device or service type.
CreateAsyncFind | Method that creates an asynchronous search.
StartAsyncFind | Method that starts an asynchronous search.
CancelAsyncFind | Method that cancels an asynchronous search.
FindByUDN | Method that searches synchronously for a device by its unique device name (UDN).

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPDeviceFinder::CancelAsyncFind

The IUPnPDeviceFinder::CancelAsyncFind method cancels an asynchronous search.

HRESULT CancelAsyncFind(
  LONG lFindData
);

Parameters

lFindData
[in] Specifies the search to cancel. The value of lFindData is the value returned by a previous call to IUPnPDeviceFinder::CreateAsyncFind.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

Applications can keep asynchronous searches running until the application exits. Always cancel outstanding operations when exiting an application.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::CreateAsyncFind, IUPnPDeviceFinder::StartAsyncFind


IUPnPDeviceFinder::CreateAsyncFind

The IUPnPDeviceFinder::CreateAsyncFind method creates an asynchronous search operation.

HRESULT CreateAsyncFind(
  BSTR bstrTypeURI,
  DWORD dwFlags,
  IUnknown *punkDeviceFinderCallback,
  LONG *plFindData
);

Parameters

bstrTypeURI
[in] Specifies the uniform resource identifier (URI) for which to search.
dwFlags
[in] Specify zero. This parameter is reserved for future use.
punkDeviceFinderCallback
[in] Reference to an IUnknown that specifies the callback UPnP uses to notify the caller when the search is complete.
plFindData
[out] Receives a reference to a LONG that receives the identifier for this particular search. The application must supply this identifier to other asynchronous search methods that are called.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method returns immediately; UPnP notifies the caller of any search results using the callback specified by punkDeviceFinderCallback. This method returns a search identifier; the caller must use the IUPnPDeviceFinder::StartAsyncSearch to actually begin the search.

The object referred to by pUnkCallback must either support the IUPnPDeviceFinderCallback interface, or the IDispatch interface. The IUPnPDeviceFinder::CreateAsyncFind method first queries pUnkCallback for the IUPnPDeviceFinderCallback interface. If this interface is not supported, the IUPnPDeviceFinder::CreateAsyncFind method then queries pUnkCallback for the IDispatch interface. If the IDispatch interface is not supported, both checks have failed and the IUPnPDeviceFinder::CreateAsyncFind method returns E_FAIL.

If only IDispatch is supported, the Service object invokes the callback by calling IDispatch::Invoke with the dispatch ID specified as zero, which indicates the default method. This default IDispatch method is passed the same parameters as the IUPnPDeviceFinderCallback method, but the first parameter passed is a string that indicates the reason the callback is invoked. Valid values are 0, 1, and 2.

In VBScript, the second argument must be GetRef(funcname), where funcname is the name of the callback subroutine.

The callback function must be declared with three parameters, and uses the values specified for each parameter:

  • param1 is the Device object of the new device; it is only valid when param3 is zero.
  • param2 is the UDN of the found or removed device; it is only valid when param3 is zero or one.
  • param3 is the type of callback. Valid values are:

    0 – indicates a new device,

    1 – indicates a device has been removed,

    2 – indicates the search is complete.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::StartAsyncFind


IUPnPDeviceFinder::FindByType

The IUPnPDeviceFinder::FindByType method performs a synchronous search for devices by device or service type.

HRESULT FindByType(
  BSTR bstrTypeURI,
  DWORD dwFlags,
  IUPnPDevices ** pDevices
);

Parameters

bstrTypeURI
[in] Specifies the type URI for the device or service type for which to search.
dwFlags
[in] Specify zero. This parameter is reserved for future use.
pDevices
[out] Receives a reference to a collection of IUPnPDevices devices that were found.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method only searches for devices on the same subnet.

This method does not return until the search is complete. The search may take at least nine seconds, and possibly more. This method must not be called from a thread that processes user interface messages.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::FindByUDN, IUPnPDevices


IUPnPDeviceFinder::FindByUDN

The IUPnPDeviceFinder::FindByUDN method searches for a device by its unique device name (UDN).

HRESULT FindByUDN(
  BSTR bstrUDN,
  IUPnPDevice **pDevice
);

Parameters

bstrUDN
[in] Specifies the UDN for which to search.
pDevice
[out] Receives a reference to an IUPnPDevice object that contains the requested device. Receives NULL if the specified device is not found.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns S_FALSE.

Remarks

This method only searches for devices on the same subnet.

This method returns as soon as a device that matches the specified UDN is found. If no device is found, the method takes at least nine seconds to return, and possibly longer.

This method make take up to 20 seconds to return. This value is not configurable.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::FindByType, IUPnPDevices


IUPnPDeviceFinder::StartAsyncFind

The IUPnPDeviceFinder::StartAsyncFind method starts an asynchronous search operation.

HRESULT StartAsyncFind(
  LONG lFindData
);

Parameters

lFindData
[in] Specifies the search to start. The value of lFindData is the value returned by a previous call to IUPnPDeviceFinder::CreateAsyncFind.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method only searches for devices on the same subnet.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::CancelAsyncFind


IUPnPDeviceFinderCallback

The IUPnPDeviceFinderCallback interface allows UPnP to communicate the results of an asynchronous search to an application.

When to Implement

Developers should implement this interface for C++ applications that are written using the asynchronous search methods of the IUPnPDeviceFinder interface. Developers using all other programming languages, such as Visual Basic, should implement a custom callback function to receive callbacks.

When to Use

UPnP uses this callback when devices are added or removed from the network, and when an initial search is complete.

Methods and Properties in Vtable Order

IUnknown Methods

Method | Description
DeviceAdded | Indicates that a device has been added to the network.
DeviceRemoved | Indicates that a device has been removed from the network.
SearchComplete | Indicates that a search for all network devices has been completed.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPDeviceFinderCallback::DeviceAdded

The IUPnPDeviceFinderCallback::DeviceAdded method is invoked when a device has been added to the network.

HRESULT DeviceAdded(
  LONG lFindData,
  IUPnPDevice *pDevice
);

Parameters

lFindData
[in] Specifies the search for which UPnP is returning results. The value of lFindData is the value returned to the caller by IUPnPDeviceFinder::CreateAsyncFind.
pDevice
[in] Reference to a IUPnPDevice object that contains the new device.

Return Values

UPnP does not expect the application to return any specific value; any value returned is ignored by UPnP.

Remarks

UPnP may return two or more callbacks for the same device. This can happen if a device's IP address was changed without first removing the device and re-adding it to the network. If this occurs, an application should discard the old device and use the most recently returned one.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::CreateAsyncFind


IUPnPDeviceFinderCallback::DeviceRemoved

The IUPnPDeviceFinderCallback::DeviceRemoved method is invoked when a device has been removed from the network.

HRESULT DeviceRemoved(
  LONG lFindData,
  BSTR bstrUDN
);

Parameters

lFindData
[in] Specifies the search for which UPnP is returning results. The value of lFindData is the value returned to the caller by IUPnPDeviceFinder::CreateAsyncFind.
bstrUDN
[in] Specifies the UDN of the device that was removed from the network.

Return Values

UPnP does not expect the application to return a specific value; any value returned is ignored by UPnP.

Remarks

UPnP may return two or more callbacks for the same device. An application can ignore subsequent device-removal callbacks.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::CreateAsyncFind


IUPnPDeviceFinderCallback::SearchComplete

The IUPnPDeviceFinderCallback::SearchComplete method is invoked when UPnP has finished sending all the IUPnPDeviceFinderCallback::DeviceAdded callbacks to the application. These DeviceAdded callbacks show the state of the network at the time the search was started.

HRESULT SearchComplete(
  LONG lFindData
);

Parameters

lFindData
[in] Specifies the search UPnP has completed. The value of lFindData is the value returned to the caller by IUPnPDeviceFinder::CreateAsyncFind.

Return Values

UPnP does not expect the application to return a specific value; any value returned is ignored by UPnP.

Remarks

An asynchronous search continues to report devices being added to and removed from the network until the application calls IUPnPDeviceFinder::CancelAsyncFind.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDeviceFinder, IUPnPDeviceFinder::CreateAsyncFind


IUPnPDevices

The IUPnPDevices interface enumerates a collection of devices.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

Use this interface to review the devices returned by prior searches.

Methods and Properties in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
Count | Property that returns the number of devices in the collection.
_NewEnum | Property that returns the enumerator interface for the collection. This method is not visible in Visual Basic; use the for...each programming construct instead.
Item | Property that returns an IUPnPDevice object for the specified device in the collection.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPDevices::_NewEnum

The IUPnPDevices::_NewEnum property returns either the IEnumVARIANT or IEnumUnknown enumerator interface for the collection. Use this method to retrieve each object in the collection.

HRESULT _NewEnum(
  LPUNKNOWN *ppunk
);

Parameters

ppunk
[out] Receives a reference to the enumerator interface.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method is not visible in Visual Basic; use the for...each programming construct instead.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevices


IUPnPDevices::Count

The IUPnPDevices::Count property returns the number of devices in the collection.

HRESULT Count(
  long *plCount
);

Parameters

plCount
[out] Receives a reference to the number of devices in the collection.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevices


IUPnPDevices::Item

The IUPnPDevices::Item property returns an IUPnPDevice object for the specified device in the collection. Use the UDN to identify the device to return.

HRESULT Item(
  BSTR bstrUDN,
  IUPnPDevice **ppDevice
);

Parameters

bstrUDN
[in] Specifies the device to return.
ppDevice
[out] Receives a reference to an IUPnPDevice object that contains the requested device.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPDevices


IUPnPService

The IUPnPService interface enables an application to query state variables and invoke actions on an instance of a service.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

Use this interface to control a device.

Methods and Properties in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
QueryStateVariable | Method that returns the value of the specified state variable.
InvokeAction | Method that invokes the specified action.
ServiceTypeIdentifier | Property that returns the service type identifier for the service.
AddCallback | Method that registers a service callback.
Id | Property that returns the service ID for the service.
LastTransportStatus | Property that returns the HTTP status of the last request sent to the service on the device It is either a request to invoke an action, or query the value of a non-evented state variable.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPService::AddCallback

The IUPnPService::AddCallback method registers an application's callback with UPnP.

HRESULT AddCallback(
  IUnknown *pUnkCallback
);

Parameters

pUnkCallback
[in] Specifies the reference to the interface that contains the callback to register.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

Do not call this method from within a callback; memory corruption occurs.

If more than one callback is registered, UPnP invokes the callbacks sequentially.

The object referred to by pUnkCallback must either support the IUPnPServiceCallback interface, or the IDispatch interface. The IUPnPService::AddCallback method first queries pUnkCallback for the IUPnPServiceCallback interface. If this interface is not supported, the IUPnPService::AddCallback method then queries pUnkCallback for the IDispatch interface. If the IDispatch interface is not supported, both checks have failed and the IUPnPService::AddCallback method returns E_FAIL.

If only IDispatch is supported, the Service object invokes the callback by calling IDispatch::Invoke with the dispatch ID specified as zero, which indicates the default method. This default IDispatch method is passed the same parameters as the IUPnPServiceCallback method, but the first parameter passed is a string that indicates the reason the callback is invoked. Valid values are VARIABLE_UPDATE and SERVICE_INSTANCE_DIED.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService, IUPnPServiceCallback


IUPnPService::Id

The IUPnPService::Id property returns the service ID for the service.

HRESULT Id(
  BSTR *pbstrId
);

Parameters

pbstrId
[out] Receives a reference to the service ID. The string returned must be freed using SysFreeString().

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService


IUPnPService::InvokeAction

The IUPnPService::InvokeAction method invokes an action of the device.

HRESULT InvokeAction(
  BSTR bstrActionName,
  VARIANT vInActionArgs,
  VARIANT *vpOutActionArgs,
  VARIANT *pvRetVal
);

Parameters

bstrActionName
[in] Specifies the method to invoke.
vInActionArgs
[in] Specifies an array of input arguments to the method. If the action has no input arguments, this parameter must contain an empty array.

The contents of this array are service-specific.

vpOutActionArgs
[in, out] On input, contains a reference to an empty array.

On output, receives a reference to the array of output arguments. If the action has no output arguments, this parameter contains an empty array.

The contents of this parameter are service-specific.

pvRetVal
[out] Receives a reference to a VARIANT that contains the return value of this action. If this action does not return a value, this parameter is NULL.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h, or one of the following UPnP-specific return values.

HRESULT value | Description
UPNP_E_ACTION_REQUEST_FAILED | The device had an internal error; the request could not be executed.
UPNP_E_DEVICE_ERROR | An unknown error occurred.
UPNP_E_DEVICE_TIMEOUT | The device has not responded within the 30 second time-out period.
UPNP_E_ERROR_PROCESSING_RESPONSE | The device has sent a response that cannot be processed, for example, the response was corrupted.
UPNP_E_INVALID_ACTION | The action is not supported by the device.
UPNP_E_INVALID_ARGUMENTS | One or more of the arguments passed in vInActionArgs is invalid.
UPNP_E_PROTOCOL_ERROR | An error occurred at the UPnP control protocol level.
UPNP_E_TRANSPORT_ERROR | An HTTP error occurred. Use the IUPnPService::LastTransportStatus property to obtain the actual HTTP status code.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService


IUPnPService::LastTransportStatus

For queries related to evented variables, the IUPnPService::LastTransportStatus property returns the HTTP status of the last IUPnPService::InvokeAction operation. For queries related to non-evented variables, the LastTransportStatus property returns the last IUPnPService::QueryStateVariable operation, if the caller invoked a query for a non-evented variable.

HRESULT LastTransportStatus(
  long *plValue
);

Parameters

plValue
[out] Receives a reference to the status. If plValue is 200, the operation was successful.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService


IUPnPService::QueryStateVariable

The IUPnPService::QueryStateVariable method returns the value of one of the service's state variables.

HRESULT QueryStateVariable(
  BSTR bstrVariableName,
  VARIANT *pValue
);

Parameters

bstrVariableName
[in] Specifies the state variable for which to return a value.
pValue
[out] Receives a reference to the value of the variable specified by bstrVariableName. The type of the data returned depends on the state variable for which the query was invoked.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns either one of the COM error codes defined in WinError.h, or one of the following UPnP-specific return values.

UPnP-specific return value | Description
UPNP_E_DEVICE_ERROR | Variable is not evented and the remote query returned an error code. This is not a transport error; the device received the request, but it returned an error.
UPNP_E_DEVICE_TIMEOUT | The device has not responded within the 30 second time-out period.
UPNP_E_INVALID_VARIABLE | Variable does not exist.
UPNP_E_PROTOCOL_ERROR | Query was not completed because of problems at the UPnP protocol level.
UPNP_E_TRANSPORT_ERROR | Variable is not evented and the remote query for the value failed because of an HTTP problem. Use IUPnPService::LastTransportStatus to retrieve the HTTP error code.
UPNP_E_VARIABLE_VALUE_UNKNOWN | Variable is evented, but UPnP cannot return a value because UPnP is still waiting for an event notification.

Remarks

This method retrieves the values of evented variables from the service object's local cache. The cache contains the value for each variable indicated in the last event notification. This method retrieves the values of non-evented variables by sending a remote query to the device.

If an application invokes this method for an evented state variable, and invokes it between the time a service first initializes itself and the time it processes its first event, UPNP_E_VARIABLE_VALUE_UNKNOWN is returned.

If an application invokes this method for a service that does not use events, and the HTTP request fails, UPNP_E_TRANSPORT_ERROR is returned. Use IUPnPService::LastTransportStatus to view the status.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService, IUPnPService::LastTransportStatus


IUPnPService::ServiceTypeIdentifier

The IUPnPService::ServiceTypeIdentifier property returns the service type identifier for the device.

HRESULT ServiceTypeIdentifier(
  BSTR *pVal
);

Parameters

pVal
[out] Receives a reference to a string that contains the service type identifier. This string must be released when it is no longer required by calling SysFreeString().

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService


IUPnPServiceCallback

The IUPnPServiceCallback interface is used to send event notifications to clients of Service objects.

When to Implement

Developers should implement this interface for C++ applications that are written to receive event notifications from a service. Developers using all other programming languages, such as Visual Basic, should implement a custom callback function to receive callbacks.

When to Use

UPnP invokes this callback when an event occurs.

Methods and Properties in Vtable Order

IUnknown Methods

Method | Description
StateVariableChanged | Indicates that a state variable has changed.
ServiceInstanceDied | Indicates that a service will no longer be sending events.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPServiceCallback::ServiceInstanceDied

The IUPnPServiceCallback::ServiceInstanceDied method is invoked when a service is no longer sending events.

HRESULT ServiceInstanceDied(
  IUPnPService *pus
);

Parameters

pus
[in] Reference to an IUPnPService object that specifies the service about which UPnP is sending the notification.

Return Values

UPnP does not expect the application to return a specific value; any value returned is ignored by UPnP.

Remarks

UPnP invokes this method when a service either has notified UPnP that it is no longer sending events or UPnP fails to maintain its connection to a service.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService, IUPnPService::AddCallback


IUPnPServiceCallback::StateVariableChanged

The IUPnPServiceCallback::StateVariableChanged method is invoked when a state variable has changed.

HRESULT StateVariableChanged(
  IUPnPService *pus,
  LPCWSTR pcwszStateVarName,
  VARIANT vaValue
);

Parameters

pus
[in] Reference to an IUPnPService object that specifies the service about which UPnP is sending the notification.
pcwszStateVarName
[in] Reference to a string that specifies the state variable that has changed.
vaValue
[in] Specifies the new value. The type of the data returned depends on the data type of the state variable about which the notification is being sent.

Return Values

UPnP does not expect the application to return a specific value; any value returned is ignored by UPnP.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPService, IUPnPService::AddCallback


IUPnPServices

The IUPnPServices interface enumerates a collection of services.

When to Implement

You should not implement this interface. The Microsoft standard implementation provides complete functionality.

When to Use

Use this interface to review the services returned by UPnP.

Be aware that use of these methods causes UPnP to contact the service across the network. If the service does not exist, the application is blocked until the connect request fails. It is recommended that applications use the Item method in most instances, and reserve the enumeration for instances when an application is starting up.

Methods in Vtable Order

IUnknown Methods

IDispatch Methods

Method | Description
Count | Property that returns the number of services in the collection.
_NewEnum | Property that returns the enumerator interface for the collection. This method is not visible in Visual Basic; use the for...each programming construct instead.
Item | Property that returns the IUPnPService object for the specified service in the collection.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.


IUPnPServices::_NewEnum

The IUPnPServices::_NewEnum property returns either the IEnumVARIANT or IEnumUnknown enumerator interface for the collection.

HRESULT _NewEnum(
  LPUNKNOWN *ppunk
);

Parameters

ppunk
[out] Receives a reference to the enumerator interface.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Remarks

This method is not visible in Visual Basic; use the for...each programming construct instead.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPServices


IUPnPServices::Count

The IUPnPServices::Count property returns the number of services in the collection.

HRESULT Count(
  long *plCount
);

Parameters

plCount
[out] Receives a reference to the number of services in the collection.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPServices


IUPnPServices::Item

The IUPnPServices::Item property returns the IUPnPService object for the specified service in the collection. Use the service ID to identify the service to return.

HRESULT Item(
  BSTR bstrServiceID,
  IUPnPService **ppService
);

Parameters

bstrServiceID
[in] Specifies the service to return.
ppService
[out] Receives a reference to an IUPnPService object that contains the requested service.

Return Values

If the method succeeds, the return value is S_OK. Otherwise, the method returns one of the COM error codes defined in WinError.h.

Requirements

Windows NT/2000 or later: Requires Whistler.
Windows 95/98/Me: Requires Windows Me.
Header: Upnp.idl.
Library: Included as a resource in Upnp.dll.

See Also

IUPnPServices


Glossary

A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z


A

action
An action represents a command that a client issues to perform a specific function. It takes zero or more arguments.
announce
Announcing a device on a network means that messages are multicast to all nodes in the subnet.
argument
An argument is a parameter to an action.


C

control point
A control point is a controller (such as an application) that retrieves device and service descriptions, sends actions to services, queries service state variables and receives events from services. Applications that allow a user to use or run a device, such as a CD player device, are considered control points.


D

device
A device is a container of other services or devices. A device may contain other logical devices.
device description
A device description is a list of the generic properties of all the devices in a physical device, including the services, the device's hierarchy, and its properties.
device type
A standard device type is denoted by urn:schemas-upnp-org:device: followed by a unique name assigned by a UPnP forum working committee.

There is a one-to-one relationship between UPnP device templates and device types. UPnP vendors may specify additional device types; these are denoted by urn:domain-name:device: followed by a unique name assigned by the vendor, where domain-name is a domain name registered to the vendor.


E

event
An event is a notification of one or more changes in state variables exposed by a service.
evented variable
An evented variable is a state variable for a service that, when changed, triggers an event. Any control points that are subscribed to a variable's event source then receives notification of the change. A non-evented state variable is never included in an event notification.


P

property
See state variable.
publish
Publishing a device means that a device is made available on the network.


R

root device
A root device is the top-most device in a device tree. For example, if you are accessing a VCR/TV combination device called a viewing station, there are three devices: the viewing station, the VCR, and the TV. The viewing station is considered the root device.


S

service
A service is a logical functional unit. Services expose actions and model some or all of the states of a physical device using state variables.
service description
A service description is a list of the actions a service provides, and the state variables associated with the actions.
service type
A standard service type is denoted by urn:schemas-upnp-org:service: followed by a unique name (assigned by a UPnP forum working committee), a colon, and a version number.

There is a one-to-one relationship between a UPnP service template and a service type. UPnP vendors may specify additional services; these are denoted by urn:domain-name:service: followed by a unique name assigned by the vendor, a colon, and a version number, where domain-name is a domain name registered to the vendor.

state variable
A state variable is a piece of data that describes some part of a service's state.


U

UDN
Stands for unique device name. A UDN uniquely identifies a device; it is also known as a UUID (universal unique ID).


Topic Not Found

No matching topic was found. Some possible reasons and remedies are as follows:

  • The file (.chm) that contains the destination topic is not in the expected location.

    Remedy: Rerun the MSDN Library Setup.

  • The file (.chm) that contains the current topic or destination topic is out-of-date and the link is no longer valid.

    Remedy: Install the latest version of the MSDN Library.

  • The MSDN Library CD is not in the CD-ROM drive.

    Remedy: Insert the MSDN Library CD into the CD-ROM drive.