Beispiel #1
0
/**
 *  This method is called when we receive a WPD_COMMAND_OBJECT_RESOURCES_OPEN
 *  command.
 *
 *  The parameters sent to us are:
 *  - WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID: the object identifier of the
 *      object which contains the specified resource
 *
 *  - WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS: the specified resource
 *      to open
 *
 *  - WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE: the access mode to which to
 *      open the specified resource
 *
 *  The driver should:
 *  - Create a new context for this resource operation.
 *  - Return an identifier for the context in WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT.
 *  - Set the optimal transfer size in WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE
 *
 */
HRESULT WpdObjectResources::OnOpenResource(
    _In_ IPortableDeviceValues*  pParams,
    _In_ IPortableDeviceValues*  pResults)
{
    HRESULT     hr              = S_OK;
    LPWSTR      wszObjectID     = NULL;
    PROPERTYKEY Key             = WPD_PROPERTY_NULL;
    DWORD       dwMode          = STGM_READ;
    CAtlStringW strStrObjectID;
    CAtlStringW strResourceContext;
    ContextMap* pContextMap     = NULL;

    // Get the Object identifier of the object which contains the specified resource
    hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID, &wszObjectID);
    if (hr != S_OK)
    {
        hr = E_INVALIDARG;
        CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_OBJECT_ID");
    }

    // Get the resource key
    if (hr == S_OK)
    {
        hr = pParams->GetKeyValue(WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS, &Key);
        CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_RESOURCE_KEYS");
    }

    // Get the access mode
    if (hr == S_OK)
    {
        hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE, &dwMode);
        CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_ACCESS_MODE");
    }

    // Validate whether the params given to us are correct.  In this case, we need to check that the object
    // supports the resource requested, and can be opened in the requested access mode.
    if (hr == S_OK)
    {
        // In this sample, we only have one object (README_FILE_OBJECT_ID) which supports a
        // resource (WPD_RESOURCE_DEFAULT) for reading only.
        // So if any other Object ID or any other resource is specified, it must be invalid.
        strStrObjectID = wszObjectID;
        if(strStrObjectID.CompareNoCase(README_FILE_OBJECT_ID) != 0)
        {
            hr = E_INVALIDARG;
            CHECK_HR(hr, "Object [%ws] does not support resources", wszObjectID);
        }
        if (hr == S_OK)
        {
            if (!IsEqualPropertyKey(Key, WPD_RESOURCE_DEFAULT))
            {
                hr = E_INVALIDARG;
                CHECK_HR(hr, "Only WPD_RESOURCE_DEFAULT is supported in this sample driver");
            }
        }
        if (hr == S_OK)
        {
            if ((dwMode & STGM_WRITE) != 0)
            {
                hr = E_ACCESSDENIED;
                CHECK_HR(hr, "This resource is not available for write access");
            }
        }
    }

    // Get the context map which the driver stored in pParams for convenience
    if (hr == S_OK)
    {
        hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap);
        CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP");
    }

    // Create a new resource operation context, initialize it, and add it to the client context map.
    if (hr == S_OK)
    {
        WpdObjectResourceContext* pResourceContext = new WpdObjectResourceContext();
        if (pResourceContext != NULL)
        {
            // Initialize the resource context with ...
            pResourceContext->m_strObjectID      = wszObjectID;
            pResourceContext->m_Resource         = Key;
            pResourceContext->m_BytesTransferred = 0;
            pResourceContext->m_BytesTotal       = GetObjectSize(wszObjectID);

            // Add the resource context to the context map
            pContextMap->Add(pResourceContext, strResourceContext);

            // Release the resource context because it has been AddRef'ed during Add()
            SAFE_RELEASE(pResourceContext);
        }
        else
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, "Failed to allocate resource context");
        }
    }

    if (hr == S_OK)
    {
        hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, strResourceContext);
        CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT");
    }

    // Set the optimal buffer size
    if (hr == S_OK)
    {
        hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE, FILE_OPTIMAL_READ_BUFFER_SIZE_VALUE);
        CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_OPTIMAL_TRANSFER_BUFFER_SIZE value");
    }

    // Free the memory.  CoTaskMemFree ignores NULLs so no need to check.
    CoTaskMemFree(wszObjectID);

    SAFE_RELEASE(pContextMap);

    return hr;
}
Beispiel #2
0
/**
 *  This method is called when we receive a WPD_COMMAND_OBJECT_ENUMERATION_START_FIND
 *  command.
 *
 *  The parameters sent to us are:
 *  - WPD_PROPERTY_OBJECT_ENUMERATION_PARENT_ID: the parent where we should start
 *      the enumeration.
 *  - WPD_PROPERTY_OBJECT_ENUMERATION_FILTER: the filter to use when doing
 *      enumeration.  Since this parameter is optional, it may not exist.
 *      This driver currently ignores the filter parameter.
 *
 *  The driver should:
 *  - Create a new context for this enumeration.
 *  - Set the string identifier in WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT for the newly created enumeration context.
 *    This value will be passed back during OnFindNext and OnEndFind.
 */
HRESULT WpdObjectEnumerator::OnStartFind(
    _In_    IPortableDeviceValues*  pParams,
    _Inout_ IPortableDeviceValues*  pResults)
{
    HRESULT      hr              = S_OK;
    LPWSTR       wszParentID     = NULL;
    ContextMap*  pContextMap     = NULL;
    CAtlStringW  strEnumContext;

    // First get ALL parameters for this command.  If we cannot get ALL parameters
    // then E_INVALIDARG should be returned and no further processing should occur.

    // Get the object identifier of the parent where the enumeration is starting from.
    hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_ENUMERATION_PARENT_ID, &wszParentID);
    if (hr != S_OK)
    {
        hr = E_INVALIDARG;
        CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_ENUMERATION_PARENT_ID");
    }

    // Get the client context map so we can store an enumeration context for this enumeration
    // operation.
    if (hr == S_OK)
    {
        hr = GetClientContextMap(pParams, &pContextMap);
        CHECK_HR(hr, "Failed to get client context map");
    }

    // Create and initialize a new enumeration context.
    // Add the new enumertion context to the client context map.  This context is used to
    // keep track of this particular enumeration operation.
    if (hr == S_OK)
    {
        WpdObjectEnumeratorContext* pEnumeratorContext = new WpdObjectEnumeratorContext();

        if (pEnumeratorContext != NULL)
        {
            ACCESS_SCOPE Scope = m_pDevice->GetAccessScope(pParams);
            m_pDevice->InitializeEnumerationContext(Scope, wszParentID, pEnumeratorContext);

            // Add the enumeration context to the client context map.  This calls AddRef() on pEnumeratorContext
            hr = pContextMap->Add(pEnumeratorContext, strEnumContext);
            CHECK_HR(hr, "Failed to add the enumeration context");
        }
        else
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, "Failed to allocate enumeration context");
        }

        SAFE_RELEASE(pEnumeratorContext);
    }

    // Set the WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT value in the results.
    // This context identifier will be passed back during OnFindNext and OnEndFind to allow the driver to access it.
    if (hr == S_OK)
    {
        hr = pResults->SetStringValue(WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT, strEnumContext);
        CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_ENUMERATION_CONTEXT");
    }

    // Free the memory.  CoTaskMemFree ignores NULLs so no need to check.
    CoTaskMemFree(wszParentID);

    SAFE_RELEASE(pContextMap);

    return hr;
}
HRESULT WpdServiceMethods::StartMethod(
    _In_                           IPortableDeviceValues*  pParams,
    _Outptr_result_nullonfailure_  LPWSTR*                 ppwszMethodContext)
{
    HRESULT                 hr          = S_OK;
    ContextMap*             pContextMap = NULL;
    ServiceMethodContext*   pContext    = NULL;
    GUID                    Method      = GUID_NULL;

    CAtlStringW  strKey;
    CComPtr<IPortableDeviceValues> pMethodParams;

    if((pParams         == NULL)  ||
       (ppwszMethodContext    == NULL))
    {
        hr = E_POINTER;
        CHECK_HR(hr, "Cannot have NULL parameter");
        return hr;
    }

    *ppwszMethodContext = NULL;

    // Check if the method is supported
    hr = pParams->GetGuidValue(WPD_PROPERTY_SERVICE_METHOD, &Method);
    CHECK_HR(hr, "Failed to get WPD_PROPERTY_SERVICE_METHOD");

    if (SUCCEEDED(hr) && !m_pContactsService->IsMethodSupported(Method))
    {
        hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
        CHECK_HR(hr, "Unknown method %ws received",CComBSTR(Method));
    }

    if (SUCCEEDED(hr))
    {
        // Get the context map which the driver stored in pParams for convenience
        hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap);
        CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP");
    }

    if (SUCCEEDED(hr))
    {
        pContext = new ServiceMethodContext();
        if(pContext == NULL)
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, "Failed to allocate new method context");
        }
    }

    if (SUCCEEDED(hr))
    {
        hr = pContextMap->Add(pContext, strKey);
        CHECK_HR(hr, "Failed to insert method context into our context Map");
    }

    if (SUCCEEDED(hr))
    {
        hr = pContext->Initialize(this, pParams, strKey);
        CHECK_HR(hr, "Failed to initialize the method context");
    }

    if (SUCCEEDED(hr))
    {
        *ppwszMethodContext = AtlAllocTaskWideString(strKey);
        if (*ppwszMethodContext == NULL)
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, "Failed to allocate method context string");
        }
    }

    SAFE_RELEASE(pContextMap);
    SAFE_RELEASE(pContext);

    return hr;
}
/**
 * Save the client information
 */
HRESULT WpdBaseDriver::OnSaveClientInfo(
    _In_    IPortableDeviceValues* pParams,
    _In_    IPortableDeviceValues* pResults)
{
    HRESULT         hr              = S_OK;
    GUID            guidContext     = GUID_NULL;
    CComBSTR        bstrContext;
    ClientContext*  pContext        = NULL;
    ContextMap*     pContextMap     = NULL;

    CComPtr<IPortableDeviceValues> pClientInfo;

    if((pParams    == NULL) ||
       (pResults   == NULL))
    {
        hr = E_POINTER;
        CHECK_HR(hr, "Cannot have NULL parameter");
        return hr;
    }

    hr = CoCreateGuid(&guidContext);
    if (hr == S_OK)
    {
        bstrContext = guidContext;
        if(bstrContext.Length() == 0)
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, "Failed to create BSTR from GUID");
        }
    }

    // Get the client info
    if (hr == S_OK)
    {
        hr = pParams->GetIPortableDeviceValuesValue(WPD_PROPERTY_COMMON_CLIENT_INFORMATION, &pClientInfo);
        CHECK_HR(hr, "Failed to get WPD_PROPERTY_COMMON_CLIENT_INFORMATION");
    }

    // Get the context map which the driver stored in pParams for convenience
    if (hr == S_OK)
    {
        hr = pParams->GetIUnknownValue(PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP, (IUnknown**)&pContextMap);
        CHECK_HR(hr, "Failed to get PRIVATE_SAMPLE_DRIVER_CLIENT_CONTEXT_MAP");
    }

    // Create the new client info context we will save in the context map
    if (hr == S_OK)
    {
        pContext = new ClientContext();
        if(pContext == NULL)
        {
            hr = E_OUTOFMEMORY;
            CHECK_HR(hr, ("Could not allocate memory for client info context"));
        }
    }

    // Save the client info.  Since these are optional, none of this is fatal if
    // they don't exist.
    if (hr == S_OK)
    {
        LPWSTR pszClientName    = NULL;
        LPWSTR pszEventCookie   = NULL;

        pClientInfo->GetStringValue(WPD_CLIENT_NAME, &pszClientName);
        if(pszClientName != NULL)
        {
            pContext->ClientName = pszClientName;
        }
        pClientInfo->GetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, &(pContext->MajorVersion));
        pClientInfo->GetUnsignedIntegerValue(WPD_CLIENT_MINOR_VERSION, &(pContext->MinorVersion));
        pClientInfo->GetUnsignedIntegerValue(WPD_CLIENT_REVISION,      &(pContext->Revision));
        
        pClientInfo->GetStringValue(WPD_CLIENT_EVENT_COOKIE, &pszEventCookie);
        if (pszEventCookie != NULL)
        {
            pContext->EventCookie = pszEventCookie;
        }

        CoTaskMemFree(pszClientName);
        CoTaskMemFree(pszEventCookie);
    }

    if ((hr == S_OK) &&
        (pContext->ClientName.GetLength() > 0) &&
        (pContextMap != NULL))
    {
        CAtlStringW strKey = bstrContext;
        hr = pContextMap->Add(strKey, pContext);
        CHECK_HR(hr, "Failed to add client info context to context map");

        if (hr == S_OK)
        {
            hr = pResults->SetStringValue(WPD_PROPERTY_COMMON_CLIENT_INFORMATION_CONTEXT, bstrContext);
            CHECK_HR(hr, "Failed to set WPD_PROPERTY_COMMON_CLIENT_INFORMATION_CONTEXT");
        }
    }

    SAFE_RELEASE(pContext); // Always release the context, pContextMap::Add would have AddRef'ed it
    SAFE_RELEASE(pContextMap);

    return hr;
}