Microsoft KB Archive/870650

= FIX: Cannot access detailed network transport property information in Windows Media Services 9 Series =

Article ID: 870650

Article Last Modified on 8/12/2004

-

APPLIES TO


 * Microsoft Windows Media Services 9 Series
 * Windows Media Services 9 Series Software Development Kit

-





SUMMARY
''This article discusses the new IWMSTransportProperties interface for Microsoft Windows Media Services 9 Series. This article includes information about how to obtain the interface, about the methods that the interface exposes, and about how to implement the interface.''




 * SYMPTOMS
 * RESOLUTION
 * Hotfix information
 * File information
 * Header file information
 * MORE INFORMATION
 * Methods that the IWMSTransportProperties interface exposes
 * CreateGlobalProperties
 * CreateStreamProperties
 * DeleteGlobalProperties
 * DeleteStreamProperties
 * GetGlobalProperties
 * GetNumAlternateStreamProperties
 * GetStreamProperties
 * SetStreamProperties
 * Retrieving the UDP port number of a client
 * Sample code
 * C++ sample code
 * C# sample code
 * REFERENCES



SYMPTOMS
You cannot programmatically access detailed network transport property information in Windows Media Services 9 Series. The server and the data sink plug-in use these network transport properties during the media streaming process. They use the transport property information to set up network connections when the client sends an RTSP SETUP request to the server. Additionally, they use the transport property information for equivalent actions when other protocols are used.

back to the top



RESOLUTION
Add the IWMSTransportProperties interface to your system. The IWMSTransportProperties interface includes methods to retrieve, to add, or to update network transport properties.

back to the top

Hotfix information
A supported hotfix is now available from Microsoft, but it is only intended to correct the problem that is described in this article. Only apply it to systems that are experiencing this specific problem. This hotfix may receive additional testing. Therefore, if you are not severely affected by this problem, we recommend that you wait for the next release that contains this hotfix.

The following file is available for download from the Microsoft Download Center:

Download the WindowsMedia9-KB870650-x86-ENU.exe package now.

For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:

119591 How to Obtain Microsoft Support Files from Online Services

Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file.

back to the top

File information
The English version of this hotfix has the file attributes (or later) that are listed in the following table. The dates and times for these files are listed in coordinated universal time (UTC). When you view the file information, it is converted to local time. To find the difference between UTC and local time, use the Time Zone tab in the Date and Time tool in Control Panel.   Date         Time   Version     Size     File name ---  16-Jul-2004  17:33  9.0.0.3666  131,072  Microsoft.windowsmediaservices.dll back to the top

Header file information
Updated header files are also available for developers who want to use this new interface. The following file is available for download from the Microsoft Download Center:

Download the WMS9SDK_KB870650_TransPropDefs.EXE package now.

The English version of this hotfix has the file attributes (or later) that are listed in the following table. The dates and times for these files are listed in coordinated universal time (UTC). When you view the file information, it is converted to local time. To find the difference between UTC and local time, use the Time Zone tab in the Date and Time tool in Control Panel.   Date         Time   Version     Size     File name ---  30-Jul-2004  18:52  9.0.0.3666  131,072  Microsoft.windowsmediaservices.dll 30-Jul-2004 18:52               32,626  Wmscontextnames.h   30-Jul-2004  18:52                3,458  Wmstransportproperties.idl 30-Jul-2004 18:52                4,356  Wmstransportpropertiesimpl.h back to the top



Methods that the IWMSTransportProperties interface exposes
Together with the methods that are inherited from the IUnknown interface, the IWMSTransportProperties interface exposes the following methods.

back to the top

CreateGlobalProperties
The IWMSTransportProperties::CreateGlobalProperties method creates the global properties that are associated with all media streams that the data sink plug-in sends out.

Syntax

HRESULT CreateGlobalProperties( IWMSContext**  ppProps,  IWMSContext*  pRelativeContext ); Parameters ppProps [out] Pointer to a pointer to an IWMSContext interface that contains the global properties. pRelativeContext [in] Pointer to an IWMSContext interface that contains the user context. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code. This method may also return a success if a NULL value or an invalid value is passed in.

back to the table

back to the top

CreateStreamProperties
The IWMSTransportProperties::CreateStreamProperties method creates the properties of a specific stream in a multimedia streaming session.

Syntax

HRESULT CreateStreamProperties( DWORD  dwStreamId,  DWORD  dwAlternateIndex,  IWMSContext**  ppProps,  IWMSContext*  pRelativeContext ); Parameters dwStreamId [in] DWORD that contains the stream ID of the stream. This value is obtained from the ASF headers. dwAlternateIndex [in] DWORD that contains the unique alternate index of the stream. ppProps [out] Pointer to a pointer to an IWMSContext interface that contains the stream properties. pRelativeContext [in] Pointer to an IWMSContext interface that contains the user context. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code. This method may also return a success if a NULL value or an invalid value is passed in.

back to the table

back to the top

DeleteGlobalProperties
The IWMSTransportProperties::DeleteGlobalProperties method deletes the global properties that are associated with all media streams that the data sink plug-in sends out.

Syntax

HRESULT DeleteGlobalProperties; Parameters

This method takes no parameters.

Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code.

back to the table

back to the top

DeleteStreamProperties
The IWMSTransportProperties::DeleteStreamProperties method deletes the properties of a specific stream in a multimedia streaming session.

Syntax

HRESULT DeleteStreamProperties( DWORD  dwStreamId,  DWORD  dwAlternateIndex ); Parameters dwStreamId [in] DWORD that contains the stream ID of the stream. This value is obtained from the ASF headers. dwAlternateIndex [in] DWORD that contains the unique alternate index of the stream. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code. This method may also return a success if a NULL value or an invalid value is passed in.

back to the table

back to the top

GetGlobalProperties
The IWMSTransportProperties::GetGlobalProperties method retrieves the global properties that are associated with all media streams that the data sink plug-in sends out.

Syntax

HRESULT GetGlobalProperties( IWMSContext**  ppProps ); Parameters ppProps [out] Pointer to a pointer to an IWMSContext interface that contains the global properties. Return Values

This method always returns S_OK. Always verify that the output pointer contains a non-NULL value before you use this method.

back to the table

back to the top

GetNumAlternateStreamProperties
The IWMSTransportProperties::GetNumAlternateStreamProperties method retrieves the number of properties that are associated with a stream.

Syntax

HRESULT GetNumAlternateStreamProperties( DWORD  dwStreamId,  DWORD*  pdwCount ); Parameters dwStreamId [in] DWORD that contains the stream ID of the stream. pdwCount [out] Pointer to a DWORD that contains the number of properties that are associated with the stream. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code. This method may also return a success if a NULL value or an invalid value is passed in. The count may return a value of 0.

back to the table

back to the top

GetStreamProperties
The IWMSTransportProperties::GetStreamProperties method retrieves the properties of a stream.

Syntax

HRESULT GetStreamProperties( DWORD  dwStreamId,  DWORD  dwAlternateIndex,  IWMSContext**  ppProps ); Parameters dwStreamId [in] DWORD that contains the stream ID of the stream. dwAlternateIndex [in] DWORD that contains the unique alternate index of the stream. ppProps [out] Pointer to a pointer to an IWMSContext interface that contains the properties of the stream. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code. This method may also return a success if a NULL value or an invalid value is passed in. Always verify that the output pointer contains a non-NULL value before you use this method.

back to the table

back to the top

SetStreamProperties
The IWMSTransportProperties::SetStreamProperties method specifies the properties of a stream.

Syntax

HRESULT SetStreamProperties( IWMSContext*  pProps,  DWORD  dwStreamId,  DWORD  dwAlternateIndex ); Parameters pProps [in] Pointer to an IWMSContext interface that contains the properties of the stream. dwStreamId [in] DWORD that contains the stream ID of the stream. dwAlternateIndex [in] DWORD that contains the unique alternate index of the stream. Return Values

If the method succeeds, it returns S_OK. If it fails, it returns an HRESULT error code.

back to the table

back to the top

Retrieving the UDP port number of a client
If you are using RTSP to stream content, you can retrieve the UDP port number of a connected client. To retrieve this value, you must create a custom event notification plug-in that accesses the RTSP SETUP request. The client sends this RTSP SETUP request during the initial setup process.

To create a custom event plug-in, follow these steps:
 * 1) Use the GetHandledEvents method and the OnEvent method to add the WMS_EVENT_SELECT_STREAMS event to the list of handled events for your plug-in.
 * 2) Retrieve a pointer to an IWMSContext interface that contains the command request context.
 * 3) Use the WMS_COMMAND_CONTEXT_STREAM_SWITCH key and the command request context to retrieve a pointer to an IWMSStreamSwitchDescriptionList interface.
 * 4) Call IWMSStreamSwitchDescriptionList::GetDescriptionCount to retrieve the number of stream descriptions in the list.
 * 5) Call IWMSStreamSwitchDescriptionList::GetIndexedDescription on each description to retrieve the CWMSStreamSwitch structure that describes stream switch information that is associated with a specific stream.
 * 6) Look at the dwModifier member and the ModifierType member of the CWMSStreamSwitch structure. If dwModifier member is set to WMS_NO_THINNING or to WMS_INTERMEDIATE_FRAME_THINNING, and the ModifierType member is set to WMS_NO_MODIFIER or to WMS_THINNING_MODIFIER, a stream is being set up. The stream number is then available in the dwNewStreamNumber member. You will use this number when you retrieve the UDP port number.
 * 7) Use the WMS_COMMAND_CONTEXT_TRANSPORT key and the command request context to retrieve a pointer to an IWMSTransportProperties interface.
 * 8) Call the IWMSTransportProperties::GetStreamProperties method to retrieve a pointer to an IWMSContext interface that contains the transport settings that were defined in the SETUP request.
 * 9) Use the pointer to the IWMSContext interface and the WMS_TRANSPORT_CONTEXT_CLIENT_PORT key to retrieve the UDP port number.

back to the top

Sample code
The following sample code describes how to retrieve the UDP port number of a connected client by using a user-defined method that is called within the OnEvent method.

back to the top

 C++ sample code HRESULT CCustomEventPlugin::GetPortNumber(IWMSCommandContext *pCommandCtx) {   // Declare the variables. DWORD                            cDescCount = 0; DWORD                            dwStreamId = -1; DWORD                            dwPortNumber; HRESULT                          hr = S_OK; IWMSContext                      *pCommandRequest = NULL; IWMSStreamSwitchDescriptionList  *pStrmSwitchDesc = NULL; IWMSTransportProperties          *pTransProp = NULL;

// Retrieve a pointer to the command request context. hr = pCommandCtx->GetCommandRequest(&pCommandRequest);

// Retrieve a pointer to an IWMSStreamSwitchDescriptionList interface. hr = pCommandRequest->GetAndQueryIUnknownValue(                                    WMS_COMMAND_CONTEXT_STREAM_SWITCH,                                     WMS_COMMAND_CONTEXT_STREAM_SWITCH_ID,                                     IID_IWMSStreamSwitchDescriptionList,                                     (IUnknown **)&pStrmSwitchDesc,                                     0); if (FAILED (hr)) goto EXIT;

// Retrieve the number of stream descriptions in the stream // descriptions list. hr = pStrmSwitchDesc->GetDescriptionCount(&cDescCount);

// After the correct stream is found, retrieve the new stream number // for that stream. for (DWORD i = 0; i < cDescCount; i++) {       CWMSStreamSwitch objStreamSwitch; ZeroMemory(&objStreamSwitch, sizeof(CWMSStreamSwitch));

hr = pStrmSwitchDesc->GetIndexedDescription(i, &objStreamSwitch);

if (SUCCEEDED (hr)) {           if ((objStreamSwitch.ModifierType == WMS_NO_MODIFIER) ||                ((objStreamSwitch.ModifierType == WMS_THINNING_MODIFIER) && ((objStreamSwitch.dwModifier == WMS_NO_THINNING) ||               (objStreamSwitch.dwModifier == WMS_INTERMEDIATE_FRAME_THINNING)))) {               dwStreamId = objStreamSwitch.dwNewStreamNumber; break; }       }    }

// Retrieve a pointer to an IWMSTransportProperties interface. hr = pContext->GetAndQueryIUnknownValue(                                        WMS_COMMAND_CONTEXT_TRANSPORT,                                         WMS_COMMAND_CONTEXT_TRANSPORT_ID,                                         IID_IWMSTransportProperties,                                         (IUnknown **)&pTransProp,                                          0); if (FAILED (hr)) goto EXIT;

// Use the new stream number to retrieve the UDP port number through // the stream properties. if (dwStreamId != -1) {       IWMSContext * pTransportCtx = NULL; hr = pTransProp->GetStreamProperties(dwStreamId,                                            0,                                             &pTransportCtx); if (SUCCEEDED (hr) ) {           // Retrieve the UDP port number of the client. hr = pTransportCtx->GetLongValue(                                    WMS_TRANSPORT_CONTEXT_CLIENT_PORT,                                     WMS_TRANSPORT_CONTEXT_CLIENT_PORT_ID,                                     (LONG *)&dwPortNumber,                                     0); }       else goto EXIT; }

EXIT: // TODO: Release temporary COM objects.

return( hr ); } back to the top

 C# sample code int GetPortNumber(IWMSCommandContext pCommandCtx) {   // Declare the variables. Guid TransportProperties_Guid = typeof(IWMSTransportProperties).GUID; Guid StreamSwitchDescriptionList_Guid = typeof( IWMSStreamSwitchDescriptionList).GUID; object oUnknownXPort; object oUnknownSS; int iPortNumber = 0; Int64 dwStreamId = -1; IWMSContext cmdCtx; IWMSContext transCtx; IWMSTransportProperties oTransProps; IWMSStreamSwitchDescriptionList oSwitchList; uint dwCount = 0;

try {       // Retrieve the command request context. pCommandCtx.GetCommandRequest(out cmdCtx);

// Retrieve an object, and then explicitly cast it as an        // IWMSStreamSwitchDescriptionList object. cmdCtx.GetAndQueryIUnknownValue(                   WMSDefines.WMS_COMMAND_CONTEXT_STREAM_SWITCH,                     WMSDefines.WMS_COMMAND_CONTEXT_STREAM_SWITCH_ID,                     ref StreamSwitchDescriptionList_Guid,                    out oUnknownSS,                     0); oSwitchList = (IWMSStreamSwitchDescriptionList) oUnknownSS;

// Retrieve the number of stream descriptions in the stream // descriptions list. oSwitchList.GetDescriptionCount( out dwCount );

// After the correct stream is found, retrieve the new stream // number for that stream. for( int z=0; z<(int)dwCount; z++) {           CWMSStreamSwitch objStreamSwitch; oSwitchList.GetIndexedDescription((uint) z,                                             out objStreamSwitch);

if ((objStreamSwitch.ModifierType == WMS_STREAM_MODIFIERS.WMS_NO_MODIFIER) ||                           ((objStreamSwitch.ModifierType ==                             WMS_STREAM_MODIFIERS.WMS_THINNING_MODIFIER) && ((objStreamSwitch.dwModifier == 0) ||                            (objStreamSwitch.dwModifier == 1)))) {               dwStreamId = objStreamSwitch.dwNewStreamNumber; break; }       }

// Retrieve an object, and then explicitly cast it as an        // IWMSTransportProperties object. cmdCtx.GetAndQueryIUnknownValue(                   WMSDefines.WMS_COMMAND_CONTEXT_TRANSPORT,                    WMSDefines.WMS_COMMAND_CONTEXT_TRANSPORT_ID,                    ref TransportProperties_Guid,                    out oUnknownXPort,                    0); oTransProps = (IWMSTransportProperties) oUnknownXPort;

// Use the new stream number to retrieve the UDP port number // through the stream properties. if (dwStreamId != -1) {           oTransProps.GetStreamProperties((uint)dwStreamId,                                            0,                                            out transCtx);

// Retrieve the UDP port number of the client. transCtx.GetLongValue(                         WMSDefines.WMS_TRANSPORT_CONTEXT_CLIENT_PORT,                          WMSDefines.WMS_TRANSPORT_CONTEXT_CLIENT_PORT_ID,                          out iPortNumber,                          0); }   }    catch (Exception ex) {       if (!ex.Message.ToLower.StartsWith(&quot;invalid index&quot;)) {           // TODO: Handle the exception. }   }

// Return the port number. return iPortNumber; } back to the top

