Win32 Portable Device WPD file to local directory Stream-Copy fails on some files

1 week ago 8
ARTICLE AD BOX

I'm trying to copy a WPD Portable Device file to a local C:\ folder. I got this code from Google and some MSDN examples. It works correctly on most files, However, for others, I get the exception: Read access violation: pDestStream was nullptr
on line:

hr = pDestStream->Write(pObjectData, cbBytesRead, &cbBytesWritten);

Note that this code is in the utility function streamCopy which I got from some examples, also shown below.

The outer code is:

std::wstring destinationFilename = ...; // Where to copy to std::wstring specialDeviceObjectId = ...; // Object ID on WPD device CComPtr<IPortableDeviceResources> pResources; CComPtr<IStream> pObjectDataStream; CComPtr<IStream> pFinalFileStream; DWORD cbOptimalTransferSize = 0; HRESULT hrResources = pContent->Transfer(&pResources); // Get the stream from the device HRESULT hrGetStream = pResources->GetStream( specialDeviceObjectId.c_str(), WPD_RESOURCE_DEFAULT, // Transfer the entire data STGM_READ, // Open in READ mode &cbOptimalTransferSize, &pObjectDataStream); // Create the local destination file stream HRESULT hrCreateStreamOnFile = SHCreateStreamOnFile( destinationFilename.c_str(), STGM_CREATE | STGM_WRITE, &pFinalFileStream); // Copy the data DWORD cbTotalBytesWritten = 0; // Call utility function StreamCopy HRESULT hrStreamCopy = StreamCopy(pFinalFileStream, pObjectDataStream, cbOptimalTransferSize, &cbTotalBytesWritten);

Utility function StreamCopy

// Copies data from a source stream to a destination stream using the // specified cbTransferSize as the temporary buffer size. HRESULT StreamCopy( IStream* pDestStream, IStream* pSourceStream, DWORD cbTransferSize, DWORD* pcbWritten) { HRESULT hr = S_OK; // Allocate a temporary buffer (of Optimal transfer size) for the read results to // be written to. BYTE* pObjectData = new (std::nothrow) BYTE[cbTransferSize]; if (pObjectData != NULL) { DWORD cbTotalBytesRead = 0; DWORD cbTotalBytesWritten = 0; DWORD cbBytesRead = 0; DWORD cbBytesWritten = 0; // Read until the number of bytes returned from the source stream is 0, or // an error occured during transfer. do { // Read object data from the source stream hr = pSourceStream->Read(pObjectData, cbTransferSize, &cbBytesRead); if (FAILED(hr)) { printf("! Failed to read %d bytes from the source stream, hr = 0x%lx\n", cbTransferSize, hr); } // Write object data to the destination stream if (SUCCEEDED(hr)) { cbTotalBytesRead += cbBytesRead; // Calculating total bytes read from device for debugging purposes only // THIS IS WHERE THE ERROR SOMETIMES OCCURS // pDestStream->Write: pDestStream was nullptr hr = pDestStream->Write(pObjectData, cbBytesRead, &cbBytesWritten); if (FAILED(hr)) { printf("! Failed to write %d bytes of object data to the destination stream, hr = 0x%lx\n", cbBytesRead, hr); } if (SUCCEEDED(hr)) { cbTotalBytesWritten += cbBytesWritten; // Calculating total bytes written to the file for debugging purposes only } } // Output Read/Write operation information only if we have received data and if no error has occured so far. if (SUCCEEDED(hr) && (cbBytesRead > 0)) { printf("Read %d bytes from the source stream...Wrote %d bytes to the destination stream...\n", cbBytesRead, cbBytesWritten); } } while (SUCCEEDED(hr) && (cbBytesRead > 0)); // If the caller supplied a pcbWritten parameter and we // and we are successful, set it to cbTotalBytesWritten // before exiting. if ((SUCCEEDED(hr)) && (pcbWritten != NULL)) { *pcbWritten = cbTotalBytesWritten; } // Remember to delete the temporary transfer buffer delete[] pObjectData; pObjectData = NULL; } else { printf("! Failed to allocate %d bytes for the temporary transfer buffer.\n", cbTransferSize); } return hr; }

NOTE: Wrapping that pDestStream->Write inside a if (pDestStream != nullptr) check fixed the issue. But I'm on clear on why this error sometimes occurs.

Read Entire Article