Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Dopo che un'applicazione ha recuperato un oggetto IStream, può eseguire le operazioni di lettura o scrittura necessarie usando i metodi IStream::Read o IStream::Write. Nel caso del driver di esempio, sono supportate solo le operazioni di lettura. Quando l'applicazione chiama il metodo IStream::Read, questo metodo, a sua volta, attiva una chiamata al metodo WpdObjectResources::OnReadResource del driver di dispositivo, che esegue l'operazione di lettura effettiva.
Il metodo WpdObjectResources::OnReadResource legge il numero di byte richiesto nel buffer di destinazione e quindi aggiorna il contesto della risorsa con il numero di byte trasferiti.
HRESULT WpdObjectResources::OnReadResource(
IPortableDeviceValues* pParams,
IPortableDeviceValues* pResults)
{
HRESULT hr = S_OK;
LPWSTR wszResourceContext = NULL;
DWORD dwNumBytesToRead = 0;
DWORD dwNumBytesRead = 0;
BYTE* pBuffer = NULL;
DWORD cbBuffer = 0;
WpdObjectResourceContext* pResourceContext = NULL;
ContextMap* pContextMap = NULL;
// Get the enumeration context identifier for this enumeration operation. We will
// need this to look up the specific enumeration context in the client context map.
hr = pParams->GetStringValue(WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT, &wszResourceContext);
if (hr != S_OK)
{
hr = E_INVALIDARG;
CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT");
}
// Get the number of bytes to read
if (hr == S_OK)
{
hr = pParams->GetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ, &dwNumBytesToRead);
CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_TO_READ");
}
// Get the destination buffer
if (hr == S_OK)
{
hr = pParams->GetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, &pBuffer, &cbBuffer);
CHECK_HR(hr, "Missing value for WPD_PROPERTY_OBJECT_RESOURCES_DATA");
}
// Get the client context map so we can retrieve the resource context for this resource
// operation using the WPD_PROPERTY_OBJECT_RESOURCES_CONTEXT property value obtained above.
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");
}
if (hr == S_OK)
{
pResourceContext = (WpdObjectResourceContext*)pContextMap->GetContext(wszResourceContext);
if (pResourceContext == NULL)
{
hr = E_INVALIDARG;
CHECK_HR(hr, "Missing resource context");
}
}
// Read the next chunk of data for this request
if (hr == S_OK)
{
hr = ReadDataFromResource(pResourceContext, pBuffer, dwNumBytesToRead, &dwNumBytesRead);
CHECK_HR(hr, "Failed to read %d bytes from resource", dwNumBytesToRead);
}
if (hr == S_OK)
{
hr = pResults->SetBufferValue(WPD_PROPERTY_OBJECT_RESOURCES_DATA, pBuffer, dwNumBytesRead);
CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_DATA");
}
if (hr == S_OK)
{
hr = pResults->SetUnsignedIntegerValue(WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ, dwNumBytesRead);
CHECK_HR(hr, "Failed to set WPD_PROPERTY_OBJECT_RESOURCES_NUM_BYTES_READ");
}
// Free the memory. CoTaskMemFree ignores NULLs so no need to check.
CoTaskMemFree(wszResourceContext);
// Free the memory. CoTaskMemFree ignores NULLs so no need to check.
CoTaskMemFree(pBuffer);
SAFE_RELEASE(pContextMap);
return hr;
}