Using WMDRM on your Application � Part 2

Nov 09, 2011

Getting data form your device using WMDRM API

 

hr = CoCreateInstance(CLSID_WMDRMDeviceApp,

                NULL,

                CLSCTX_INPROC_SERVER,

                IID_IWMDMDeviceApp2,

                (void**)ppWMDRMDeviceApp2);    

 

if (hr != S_OK)

{

     printf ("! Failed to CoCreate IWMDRMDeviceApp2\n");

}

 

The next step is to obtain an IWMDMDevice instance to use as an input parameter for the IWMDRMDeviceApp and IWMDRMDeviceApp2 methods.

The process of deriving the WPD device instance is covered in detail by the WPD Sample Application in the Windows SDK and MSDN® documentation and will not be repeated here.

Each WPD device is identified by a unique Plug and Play Device Identifier (PnPDeviceID) string. Similarly, each WMDM device is also identified by a unique string known as the WMDM canonical name. If the two strings can be correlated for a given WPD MTP device, a matching IWMDMDevice instance can be retrieved from the list of enumerated WMDM devices.

To associate the PnPDeviceID string of a WPD device with its WMDM canonical name we have to follow the next steps:

1.)  Replace the device interface globally unique identifier (GUID) with the WMDM interface GUID for the current WPD PnPDeviceID.

//

// Step 1: Converting a WPD PnP Device ID to a WMDM PnP Device ID

// (Error checking is omitted for brevity)

//

 

hr = pIPortableDevice->GetPnPDeviceID(&pszPnPDeviceID);

 

CAtlStringW strWMDMPnPID = pszPnPDeviceID;

 

// Truncate the WPD interface GUID

int pos = strCurrentWMDMPnPID.ReverseFind(L'{');

strWMDMPnPID = strWMDMPnPID.Left(pos);

 

// Append the WMDM interface GUID

strWMDMPnPID += L"{f33fdc04-d1ac-4e8e-9a30-19bbd4b108ae}";

 

2.)  Enumerate devices by using the WMDM API and get the canonical name for each. Convert the canonical name to a WMDM PnPDeviceID.

//

// Step 2: Enumerating the WMDM Canonical Names

// (Error checking is omitted for brevity)

//

 

hr = pWMDeviceManager2->EnumDevices2(&pWMDMEnumDevice);

if (hr == S_OK)
{
  IWMDMDevice* pWMDMDevice = NULL;

  ULONG        ulFetched   = 0;

 

  // Traverse the list of enumerated WMDM devices

 

  while(pWMDMEnumDevice->Next(1, &pWMDMDevice, &ulFetched) == S_OK)

  {

     WCHAR          wszCanonicalName[MAX_PATH] = {0};

     IWMDMDevice2*  pWMDMDevice2 = NULL;

 

     hr = pWMDMDevice->QueryInterface(IID_PPV_ARGS(&pWMDMDevice2));

 

     // Get the canonical name for the current WMDM device

 

     hr = pWMDMDevice2->GetCanonicalName(wszCanonicalName,

                   ARRAYSIZE(wszCanonicalName);

 

     CAtlStringW   strTestPnPID = wszCanonicalName;

 

     // Truncate the WMDM virtual device index

 

     int pos = strTestPnPID.ReverseFind(L'$')

     strTestPnPID = strTestPnPID.Left(pos);

 

     //

     // Do Step 3 here …

     //

  }

}

 

3.)  Call IPortableDevice::Open on the WMDM PnPDeviceID obtained from enumerating the WMDM canonical names to get the PnPDeviceID.

Although the PnPDeviceID returned from IPortableDevice::GetPnPDeviceID is the same literal string as the original WMDM PnPDeviceID from Step 1, this test “closes the loop” by ensuring that both WPD and WMDM can access the same WMDM device identifiers.

//

// Step 3: Verify that the WMDM Device ID converted from the

// Canonical Name can be accessed by WPD

// (Error checking is omitted for brevity)

//

 

IPortableDevice* pPortableDeviceTest = NULL;

IPortableDeviceValues* pClientInfo   = NULL;

 

LPWSTR           pszWPDPnPDeviceID   = NULL;

 

//

// CoCreate a new instance of IPortableDevice (not shown) …

// CoCreate and populate client information (not shown) …

//

 

hr = pIPortableDeviceTest->Open(strTestPnPID, pClientInfo);

 

if (hr == S_OK)

{

    hr = pIPortableDeviceTest->GetPnPDeviceID(&pszWPDPnPDeviceID);

 

     // Compare the result with our WMDM PnP ID

 

     if (strWMDMPnPID.CompareNoCase(pszWPDPnPDeviceID) == 0)

     {

         // Found a matching IWMDMDevice instance

     }

}

 

4.)  Now that you have found the IWMDMDevice pointer that has the correct canonical name, you can use that IWMDMDevice as the input parameter to call IWMDRMDeviceApp or IWMDRMDeviceApp2 methods on that device.

For example, the following code snippet queries if the current device supports WMDRM:

hr = pWMDRMDeviceApp2->QueryDeviceStatus2(pWMDMDevice,

                      WMDRM_QUERY_DEVICE_ISWMDRM,&dwStatus);

 

if (hr == S_OK)

{

   bool bSupportsWMDRM = (dwStatus > 0)?true:false;

}