/*++ Copyright (C) 2000 Microsoft Corporation Module Name: iso15740.cpp Abstract: This module implements methods used for manipulating PTP structures Author: Dave Parsons Revision History: --*/ #include "ptppch.h" #include // for MAKELONGLONG // // This function returns a 2 byte integer from raw data and advances the pointer // // Input: // ppRaw -- pointer to a pointer to the raw data // WORD ParseWord(BYTE **ppRaw) { WORD w; // we know that **ppRaw points to a little-endian word w = MAKEWORD((*ppRaw)[0], (*ppRaw)[1]); *ppRaw += sizeof(WORD); return w; } // // This function returns a 4 byte integer from raw data and advances the pointer // // Input: // ppRaw -- pointer to a pointer to the raw data // DWORD ParseDword(BYTE **ppRaw) { DWORD dw; // we know that **ppRaw points to a little-endian dword dw = MAKELONG(MAKEWORD((*ppRaw)[0],(*ppRaw)[1]), MAKEWORD((*ppRaw)[2],(*ppRaw)[3])); *ppRaw += sizeof(DWORD); return dw; } // // This function returns an 8 byte integer from raw data and advances the pointer // // Input: // ppRaw -- pointer to a pointer to the raw data // QWORD ParseQword(BYTE **ppRaw) { QWORD qw; // we know that **ppRaw points to a little-endian qword qw = MAKELONGLONG(MAKELONG(MAKEWORD((*ppRaw)[0],(*ppRaw)[1]), MAKEWORD((*ppRaw)[2],(*ppRaw)[3])), MAKELONG(MAKEWORD((*ppRaw)[4],(*ppRaw)[5]), MAKEWORD((*ppRaw)[6],(*ppRaw)[7]))); *ppRaw += sizeof(QWORD); return qw; } // // This function writes a 2 byte integer to a raw data buffer and advances the pointer // // Input: // ppRaw -- pointer to pointer to the raw data // value -- value to write // VOID WriteWord(BYTE **ppRaw, WORD value) { (*ppRaw)[0] = LOBYTE(LOWORD(value)); (*ppRaw)[1] = HIBYTE(LOWORD(value)); *ppRaw += sizeof(WORD); return; } // // This function writes a 4 byte integer to a raw data buffer and advances the pointer // // Input: // ppRaw -- pointer to pointer to the raw data // value -- value to write // VOID WriteDword(BYTE **ppRaw, DWORD value) { (*ppRaw)[0] = LOBYTE(LOWORD(value)); (*ppRaw)[1] = HIBYTE(LOWORD(value)); (*ppRaw)[2] = LOBYTE(HIWORD(value)); (*ppRaw)[3] = HIBYTE(HIWORD(value)); *ppRaw += sizeof(DWORD); return; } // // CBstr constructor // CBstr::CBstr() : m_bstrString(NULL) { } // // CBstr copy constructor // CBstr::CBstr(const CBstr &src) { m_bstrString = SysAllocString(src.m_bstrString); } // // CBstr destructor // CBstr::~CBstr() { if (m_bstrString) SysFreeString(m_bstrString); } // // Make a copy of a string // HRESULT CBstr::Copy(WCHAR *wcsString) { HRESULT hr = S_OK; if (m_bstrString) { if (!SysReAllocString(&m_bstrString, wcsString)) { wiauDbgError("Copy", "memory allocation failed"); return E_OUTOFMEMORY; } } else { m_bstrString = SysAllocString(wcsString); if (!m_bstrString) { wiauDbgError("Copy", "memory allocation failed"); return E_OUTOFMEMORY; } } return hr; } // // This function initializes a BSTR from a raw PTP string, clearing // the BSTR first, if needed // // Input: // ppRaw -- pointer to pointer to raw data to initialize the string from // bParse -- indicates whether to advance the raw pointer or not // HRESULT CBstr::Init( BYTE **ppRaw, BOOL bParse ) { HRESULT hr = S_OK; // // Check arguments // if (!ppRaw || !*ppRaw) { wiauDbgError("Init", "invalid arg"); return E_INVALIDARG; } // // Extract the length from the raw data, and set up a more convenient pointer // to the string data (skipping over the length byte) // int length = (UCHAR) **ppRaw; OLECHAR *pRaw = (OLECHAR *) (*ppRaw + sizeof(UCHAR)); if (m_bstrString) { if (!SysReAllocStringLen(&m_bstrString, pRaw, length)) { wiauDbgError("Init", "memory allocation failed"); return E_OUTOFMEMORY; } } else { m_bstrString = SysAllocStringLen(pRaw, length); if (!m_bstrString) { wiauDbgError("Init", "memory allocation failed"); return E_OUTOFMEMORY; } } // // If requested, advance the raw pointer past the string. One byte for the length and // 2 times the number of chars in the wide string. // if (bParse) { *ppRaw += sizeof(UCHAR) + length * sizeof(USHORT); } return hr; } // // This function writes the string to a buffer in PTP format // // Input: // ppRaw -- pointer to pointer to buffer // Length -- amount of space left in the buffer in bytes // VOID CBstr::WriteToBuffer( BYTE **ppRaw ) { UCHAR NumChars = (UCHAR) Length(); // // Add one for null terminating char, but only if string is non-empty // if (NumChars > 0) NumChars++; int NumBytes = NumChars * sizeof(WCHAR); **ppRaw = NumChars; (*ppRaw)++; if (NumChars > 0) { memcpy(*ppRaw, String(), NumBytes); *ppRaw += NumBytes; } return; } // // This function dumps a PTP string to the log // // Input: // szDesc -- Description for the string // VOID CBstr::Dump(char *szDesc) { if (m_bstrString && SysStringLen(m_bstrString) > 0) { wiauDbgDump("", "%s %S", szDesc, m_bstrString); } else { wiauDbgDump("", "%s ", szDesc); } return; } // // Dumps the contents of a CArray8 to the log // // Input: // szDesc -- description for the string // szFiller -- filler to use for subsequent lines // VOID CArray8::Dump( char *szDesc, char *szFiller ) { HRESULT hr = S_OK; char szPart[MAX_PATH] = "\0"; char szMsg[MAX_PATH] = "\0"; // // Make sure array is not empty // if (GetSize() > 0) { // // Prime output string // hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szDesc); if (FAILED(hr)) { goto Cleanup; } // // Loop through the elements // for (int count = 0; count < GetSize(); count++) { // // Start a new line every 8 values // if ((count != 0) && (count % 8 == 0)) { wiauDbgDump("", "%s", szMsg); hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szFiller); if (FAILED(hr)) { goto Cleanup; } } hr = StringCchPrintfA(szPart, ARRAYSIZE(szPart), " 0x%02x", m_aT[count]); if (FAILED(hr)) { goto Cleanup; } hr = StringCchCatA(szMsg, ARRAYSIZE(szMsg), szPart); if (FAILED(hr)) { goto Cleanup; } } wiauDbgDump("", "%s", szMsg); } else { wiauDbgDump("", "%s ", szDesc); } Cleanup: if (FAILED(hr)) { wiauDbgErrorHr(hr, "CArray8::Dump", "Failed to dump array"); } return; } // // Dumps the contents of a CArray16 to the log // // Input: // szDesc -- description for the string // szFiller -- filler to use for subsequent lines // VOID CArray16::Dump( char *szDesc, char *szFiller ) { HRESULT hr = S_OK; char szMsg[MAX_PATH] = "\0"; char szPart[MAX_PATH] = "\0"; // // Make sure it's not empty // if (GetSize() > 0) { // // Prime output string // hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szDesc); if (FAILED(hr)) { goto Cleanup; } // // Loop through the elements // for (int count = 0; count < GetSize(); count++) { // // Start a new line every 4 values // if ((count != 0) && (count % 4 == 0)) { wiauDbgDump("", "%s", szMsg); hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szFiller); if (FAILED(hr)) { goto Cleanup; } } hr = StringCchPrintfA(szPart, ARRAYSIZE(szPart), " 0x%04x", m_aT[count]); if (FAILED(hr)) { goto Cleanup; } hr = StringCchCatA(szMsg, ARRAYSIZE(szMsg), szPart); if (FAILED(hr)) { goto Cleanup; } } wiauDbgDump("", "%s", szMsg); } else { wiauDbgDump("", "%s ", szDesc); } Cleanup: if (FAILED(hr)) { wiauDbgErrorHr(hr, "CArray16::Dump", "Failed to dump array"); } return; } // // This function parses a CArray32 from an array of UCHARs // BOOL CArray32::ParseFrom8( BYTE **ppRaw, int NumSize ) { if (!ppRaw || !*ppRaw) return FALSE; RemoveAll(); // Get the number of elements from the raw data ULONG NumElems; switch (NumSize) { case 4: NumElems = MAKELONG(MAKEWORD((*ppRaw)[0], (*ppRaw)[1]), MAKEWORD((*ppRaw)[2], (*ppRaw)[3])); break; case 2: NumElems = MAKEWORD((*ppRaw)[0], (*ppRaw)[1]); break; case 1: NumElems = **ppRaw; break; default: return FALSE; } *ppRaw += NumSize; // Allocate space for the array if (!GrowTo(NumElems)) return FALSE; // Copy in the elements, one at a time BYTE *pValues = *ppRaw; ULONG value = 0; for (ULONG count = 0; count < NumElems; count++) { value = (ULONG) pValues[count]; if (!Add(value)) return FALSE; } // Advance the raw pointer past the array and number of elements field *ppRaw += NumElems * sizeof(BYTE); return TRUE; } // // This function parses a CArray32 from an array of WORDs // BOOL CArray32::ParseFrom16( BYTE **ppRaw, int NumSize ) { if (!ppRaw || !*ppRaw) return FALSE; RemoveAll(); // Get the number of elements from the raw data ULONG NumElems; switch (NumSize) { case 4: NumElems = MAKELONG(MAKEWORD((*ppRaw)[0], (*ppRaw)[1]), MAKEWORD((*ppRaw)[2], (*ppRaw)[3])); break; case 2: NumElems = MAKEWORD((*ppRaw)[0], (*ppRaw)[1]); break; case 1: NumElems = **ppRaw; break; default: return FALSE; } *ppRaw += NumSize; // Allocate space for the array if (!GrowTo(NumElems)) return FALSE; // Copy in the elements, one at a time ULONG value = 0; for (ULONG count = 0; count < NumElems; count++) { value = (ULONG) MAKEWORD((*ppRaw)[0], (*ppRaw)[1]); *ppRaw += sizeof(WORD); if (!Add(value)) return FALSE; } return TRUE; } // // Copies values from an array of bytes // BOOL CArray32::Copy(CArray8 values8) { RemoveAll(); GrowTo(values8.GetSize()); for (int count = 0; count < values8.GetSize(); count++) { ULONG value = values8[count]; if (!Add(value)) return FALSE; } return TRUE; } // // Copies values from an array of bytes // BOOL CArray32::Copy(CArray16 values16) { RemoveAll(); GrowTo(values16.GetSize()); for (int count = 0; count < values16.GetSize(); count++) { ULONG value = values16[count]; if (!Add(value)) return FALSE; } return TRUE; } // // Dumps the contents of a CArray32 to the log // // Input: // szDesc -- description for the string // szFiller -- filler to use for subsequent lines // VOID CArray32::Dump( char *szDesc, char *szFiller ) { HRESULT hr = S_OK; char szMsg[MAX_PATH] = "\0"; char szPart[MAX_PATH] = "\0"; // // Make sure it's not empty // if (GetSize() > 0) { // // Prime output string // hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szDesc); if (FAILED(hr)) { goto Cleanup; } // // Loop through the elements // for (int count = 0; count < GetSize(); count++) { // // Start a new line every 4 values // if ((count != 0) && (count % 4 == 0)) { wiauDbgDump("", "%s", szMsg); hr = StringCchCopyA(szMsg, ARRAYSIZE(szMsg), szFiller); if (FAILED(hr)) { goto Cleanup; } } hr = StringCchPrintfA(szPart, ARRAYSIZE(szPart), " 0x%08x", m_aT[count]); if (FAILED(hr)) { goto Cleanup; } hr = StringCchCatA(szMsg, ARRAYSIZE(szMsg), szPart); if (FAILED(hr)) { goto Cleanup; } } wiauDbgDump("", "%s", szMsg); } else { wiauDbgDump("", "%s ", szDesc); } Cleanup: if (FAILED(hr)) { wiauDbgErrorHr(hr, "CArray32::Dump", "Failed to dump array"); } return; } // // This function initializes a string array from raw data, clearing // the array first, if needed // // Input: // ppRaw -- pointer to pointer to raw data to initialize the string from // bParse -- indicates whether to advance the raw pointer or not // HRESULT CArrayString::Init( BYTE **ppRaw, int NumSize ) { HRESULT hr = S_OK; if (!ppRaw || !*ppRaw) return E_INVALIDARG; RemoveAll(); // Get the number of elements from the raw data int NumElems; switch (NumSize) { case 4: NumElems = MAKELONG(MAKEWORD((*ppRaw)[0],(*ppRaw)[1]), MAKEWORD((*ppRaw)[2],(*ppRaw)[3])); break; case 2: NumElems = MAKEWORD((*ppRaw)[0],(*ppRaw)[1]); break; case 1: NumElems = (BYTE) **ppRaw; break; default: return E_FAIL; } // Allocate space for the array if (!GrowTo(NumElems)) return E_OUTOFMEMORY; // Advance past the number of elements field *ppRaw += NumSize; // Read in each string CBstr tempStr; for (int count = 0; count < NumElems; count++) { tempStr.Init(ppRaw, TRUE); if (!Add(tempStr)) return E_FAIL; } return hr; } // // Dumps the contents of a CArrayString to the log // // Input: // szDesc -- description for the string // szFiller -- filler to use for subsequent lines // VOID CArrayString::Dump( char *szDesc, char *szFiller ) { int count; // // Make sure it's not empty // if (GetSize() > 0) { // // Dump first string with description // m_aT[0].Dump(szDesc); // // Loop through the elements, dumping with the filler // for (count = 1; count < GetSize(); count++) m_aT[count].Dump(szFiller); } else { wiauDbgDump("", "%s ", szDesc); } return; } // // CPtpDeviceInfo constructor // CPtpDeviceInfo::CPtpDeviceInfo() : m_Version(0), m_VendorExtId(0), m_VendorExtVersion(0), m_FuncMode(0) { } // // CPtpDeviceInfo copying constructor // CPtpDeviceInfo::CPtpDeviceInfo(const CPtpDeviceInfo &src) : m_Version(src.m_Version), m_VendorExtId(src.m_VendorExtId), m_VendorExtVersion(src.m_VendorExtVersion), m_cbstrVendorExtDesc(src.m_cbstrVendorExtDesc), m_FuncMode(src.m_FuncMode), m_cbstrManufacturer(src.m_cbstrManufacturer), m_cbstrModel(src.m_cbstrModel), m_cbstrDeviceVersion(src.m_cbstrDeviceVersion), m_cbstrSerialNumber(src.m_cbstrSerialNumber) { for (INT i = 0; i < src.m_SupportedOps.GetSize(); i++) { m_SupportedOps.Add(src.m_SupportedOps[i]); } for (i = 0; i < src.m_SupportedEvents.GetSize(); i++) { m_SupportedEvents.Add(src.m_SupportedEvents[i]); } for (i = 0; i < src.m_SupportedProps.GetSize(); i++) { m_SupportedProps.Add(src.m_SupportedProps[i]); } for (i = 0; i < src.m_SupportedCaptureFmts.GetSize(); i++) { m_SupportedCaptureFmts.Add(src.m_SupportedCaptureFmts[i]); } for (i = 0; i < src.m_SupportedImageFmts.GetSize(); i++) { m_SupportedImageFmts.Add(src.m_SupportedImageFmts[i]); } } // // CPtpDeviceInfo destructor // CPtpDeviceInfo::~CPtpDeviceInfo() { } // // This function initializes the device info from raw data // // Input: // pRawData -- the raw data // HRESULT CPtpDeviceInfo::Init(BYTE *pRawData) { HRESULT hr = S_OK; BYTE *pCurrent = pRawData; m_Version = ParseWord(&pCurrent); m_VendorExtId = ParseDword(&pCurrent); m_VendorExtVersion = ParseWord(&pCurrent); hr = m_cbstrVendorExtDesc.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; m_FuncMode = ParseWord(&pCurrent); if (!m_SupportedOps.Parse(&pCurrent)) return E_FAIL; if (!m_SupportedEvents.Parse(&pCurrent)) return E_FAIL; if (!m_SupportedProps.Parse(&pCurrent)) return E_FAIL; if (!m_SupportedCaptureFmts.Parse(&pCurrent)) return E_FAIL; if (!m_SupportedImageFmts.Parse(&pCurrent)) return E_FAIL; hr = m_cbstrManufacturer.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrModel.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrDeviceVersion.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrSerialNumber.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; return hr; } // // This function dumps the device information to the log // VOID CPtpDeviceInfo::Dump() { wiauDbgDump("", "DumpDeviceInfo, dumping DeviceInfo:"); wiauDbgDump("", " Standard version = 0x%04x", m_Version); wiauDbgDump("", " Vendor ext id = 0x%08x", m_VendorExtId); wiauDbgDump("", " Vendor ext ver = 0x%04x", m_VendorExtVersion); m_cbstrVendorExtDesc.Dump( " Vendor ext desc ="); m_SupportedOps.Dump( " Ops supported =", " "); m_SupportedEvents.Dump( " Events supported =", " "); m_SupportedProps.Dump( " Props supported =", " "); m_SupportedCaptureFmts.Dump( " Capture fmts supp =", " "); m_SupportedImageFmts.Dump( " Img formats supp =", " "); m_cbstrManufacturer.Dump( " Manufacturer ="); m_cbstrModel.Dump( " Model ="); m_cbstrDeviceVersion.Dump( " Device Version ="); m_cbstrSerialNumber.Dump( " Serial Number ="); return; } // // CPtpStorageInfo constructor // CPtpStorageInfo::CPtpStorageInfo() : m_StorageId(0), m_StorageType(0), m_FileSystemType(0), m_AccessCapability(0), m_MaxCapacity(0), m_FreeSpaceInBytes(0), m_FreeSpaceInImages(0) { } // // CPtpStorageInfo destructor // CPtpStorageInfo::~CPtpStorageInfo() { } // // This function initializes the device info from raw data // // Input: // pRawData -- the raw data // HRESULT CPtpStorageInfo::Init( BYTE *pRawData, DWORD StorageId ) { HRESULT hr = S_OK; BYTE *pCurrent = pRawData; m_StorageId = StorageId; m_StorageType = ParseWord(&pCurrent); m_FileSystemType = ParseWord(&pCurrent); m_AccessCapability = ParseWord(&pCurrent); m_MaxCapacity = ParseQword(&pCurrent); m_FreeSpaceInBytes = ParseQword(&pCurrent); m_FreeSpaceInImages = ParseDword(&pCurrent); hr = m_cbstrStorageDesc.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrStorageLabel.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; return hr; } // // This function dumps the storage information to the log // VOID CPtpStorageInfo::Dump() { wiauDbgDump("", "DumpStorageInfo, dumping StorageInfo for store 0x%08x:", m_StorageId); wiauDbgDump("", " Storage type = 0x%04x", m_StorageType); wiauDbgDump("", " File system type = 0x%04x", m_FileSystemType); wiauDbgDump("", " Access capability = 0x%04x", m_AccessCapability); wiauDbgDump("", " Max capacity = %I64u", m_MaxCapacity); wiauDbgDump("", " Free space (byte) = %I64u", m_FreeSpaceInBytes); wiauDbgDump("", " Free space (imgs) = %u", m_FreeSpaceInImages); m_cbstrStorageDesc.Dump( " Storage desc ="); m_cbstrStorageLabel.Dump( " Storage label ="); return; } // // CPtpObjectInfo constructor // CPtpObjectInfo::CPtpObjectInfo() : m_ObjectHandle(0), m_StorageId(0), m_FormatCode(0), m_ProtectionStatus(0), m_CompressedSize(0), m_ThumbFormat(0), m_ThumbCompressedSize(0), m_ThumbPixWidth(0), m_ThumbPixHeight(0), m_ImagePixWidth(0), m_ImagePixHeight(0), m_ImageBitDepth(0), m_ParentHandle(0), m_AssociationType(0), m_AssociationDesc(0), m_SequenceNumber(0) { } // // CPtpObjectInfo destructor // CPtpObjectInfo::~CPtpObjectInfo() { } // // This function initializes the object info from raw data // // Input: // pRawData -- the raw data // ObjectHandle -- the object's handle // HRESULT CPtpObjectInfo::Init( BYTE *pRawData, DWORD ObjectHandle ) { HRESULT hr = S_OK; BYTE *pCurrent = pRawData; m_ObjectHandle = ObjectHandle; m_StorageId = ParseDword(&pCurrent); m_FormatCode = ParseWord(&pCurrent); m_ProtectionStatus = ParseWord(&pCurrent); m_CompressedSize = ParseDword(&pCurrent); m_ThumbFormat = ParseWord(&pCurrent); m_ThumbCompressedSize = ParseDword(&pCurrent); m_ThumbPixWidth = ParseDword(&pCurrent); m_ThumbPixHeight = ParseDword(&pCurrent); m_ImagePixWidth = ParseDword(&pCurrent); m_ImagePixHeight = ParseDword(&pCurrent); m_ImageBitDepth = ParseDword(&pCurrent); m_ParentHandle = ParseDword(&pCurrent); m_AssociationType = ParseWord(&pCurrent); m_AssociationDesc = ParseDword(&pCurrent); m_SequenceNumber = ParseDword(&pCurrent); hr = m_cbstrFileName.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrCaptureDate.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrModificationDate.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrKeywords.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; return hr; } // // This function writes the ObjectInfo structure to a buffer in PTP format // // Input: // ppRaw -- pointer to pointer to buffer // Length -- amount of space left in the buffer in bytes // VOID CPtpObjectInfo::WriteToBuffer( BYTE **ppRaw ) { WriteDword(ppRaw, m_StorageId); WriteWord(ppRaw, m_FormatCode); WriteWord(ppRaw, m_ProtectionStatus); WriteDword(ppRaw, m_CompressedSize); WriteWord(ppRaw, m_ThumbFormat); WriteDword(ppRaw, m_ThumbCompressedSize); WriteDword(ppRaw, m_ThumbPixWidth); WriteDword(ppRaw, m_ThumbPixHeight); WriteDword(ppRaw, m_ImagePixWidth); WriteDword(ppRaw, m_ImagePixHeight); WriteDword(ppRaw, m_ImageBitDepth); WriteDword(ppRaw, m_ParentHandle); WriteWord(ppRaw, m_AssociationType); WriteDword(ppRaw, m_AssociationDesc); WriteDword(ppRaw, m_SequenceNumber); m_cbstrFileName.WriteToBuffer(ppRaw); m_cbstrCaptureDate.WriteToBuffer(ppRaw); m_cbstrModificationDate.WriteToBuffer(ppRaw); m_cbstrKeywords.WriteToBuffer(ppRaw); return; } // // This function dumps the object information to the log // VOID CPtpObjectInfo::Dump() { wiauDbgDump("", "DumpObjectInfo, dumping ObjectInfo for object 0x%08x:", m_ObjectHandle); wiauDbgDump("", " Storage id = 0x%08x", m_StorageId); wiauDbgDump("", " Format code = 0x%04x", m_FormatCode); wiauDbgDump("", " Protection status = 0x%04x", m_ProtectionStatus); wiauDbgDump("", " Compressed size = %u", m_CompressedSize); wiauDbgDump("", " Thumbnail format = 0x%04x", m_ThumbFormat); wiauDbgDump("", " Thumbnail size = %u", m_ThumbCompressedSize); wiauDbgDump("", " Thumbnail width = %u", m_ThumbPixWidth); wiauDbgDump("", " Thumbnail height = %u", m_ThumbPixHeight); wiauDbgDump("", " Image width = %u", m_ImagePixWidth); wiauDbgDump("", " Image height = %u", m_ImagePixHeight); wiauDbgDump("", " Image bit depth = %u", m_ImageBitDepth); wiauDbgDump("", " Parent obj handle = 0x%08x", m_ParentHandle); wiauDbgDump("", " Association type = 0x%04x", m_AssociationType); wiauDbgDump("", " Association desc = 0x%08x", m_AssociationDesc); wiauDbgDump("", " Sequence number = %u", m_SequenceNumber); m_cbstrFileName.Dump( " File name ="); m_cbstrCaptureDate.Dump( " Capture date ="); m_cbstrModificationDate.Dump( " Modification date ="); m_cbstrKeywords.Dump( " Keywords ="); return; } // // CPtpPropDesc constructor // CPtpPropDesc::CPtpPropDesc() : m_PropCode(0), m_DataType(0), m_GetSet(0), m_FormFlag(0), m_NumValues(0), m_lDefault(0), m_lCurrent(0), m_lRangeMin(0), m_lRangeMax(0), m_lRangeStep(0) { } // // CPtpPropDesc destructor // CPtpPropDesc::~CPtpPropDesc() { } // // This function initializes a CPtpPropDesc from raw data // // Input: // pRawData -- pointer to the raw data // HRESULT CPtpPropDesc::Init(BYTE *pRawData) { HRESULT hr = S_OK; BYTE *pCurrent = pRawData; m_PropCode = ParseWord(&pCurrent); m_DataType = ParseWord(&pCurrent); m_GetSet = *pCurrent++; switch (m_DataType) { case PTP_DATATYPE_INT8: case PTP_DATATYPE_UINT8: m_lDefault = *pCurrent++; m_lCurrent = *pCurrent++; break; case PTP_DATATYPE_INT16: case PTP_DATATYPE_UINT16: m_lDefault = ParseWord(&pCurrent); m_lCurrent = ParseWord(&pCurrent); break; case PTP_DATATYPE_INT32: case PTP_DATATYPE_UINT32: m_lDefault = ParseDword(&pCurrent); m_lCurrent = ParseDword(&pCurrent); break; case PTP_DATATYPE_STRING: hr = m_cbstrDefault.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrCurrent.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; break; default: return E_FAIL; } m_FormFlag = *pCurrent++; if (m_FormFlag == PTP_FORMFLAGS_RANGE) { switch (m_DataType) { case PTP_DATATYPE_INT8: case PTP_DATATYPE_UINT8: m_lRangeMin = *pCurrent++; m_lRangeMax = *pCurrent++; m_lRangeStep = *pCurrent++; m_lRangeStep = max(1, m_lRangeStep); break; case PTP_DATATYPE_INT16: case PTP_DATATYPE_UINT16: m_lRangeMin = ParseWord(&pCurrent); m_lRangeMax = ParseWord(&pCurrent); m_lRangeStep = ParseWord(&pCurrent); m_lRangeStep = max(1, m_lRangeStep); break; case PTP_DATATYPE_INT32: case PTP_DATATYPE_UINT32: m_lRangeMin = ParseDword(&pCurrent); m_lRangeMax = ParseDword(&pCurrent); m_lRangeStep = ParseDword(&pCurrent); m_lRangeStep = max(1, m_lRangeStep); break; case PTP_DATATYPE_STRING: hr = m_cbstrRangeMin.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrRangeMax.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; hr = m_cbstrRangeStep.Init(&pCurrent, TRUE); if (FAILED(hr)) return hr; break; default: return E_FAIL; } } else if (m_FormFlag == PTP_FORMFLAGS_ENUM) { switch (m_DataType) { case PTP_DATATYPE_INT8: case PTP_DATATYPE_UINT8: if (!m_lValues.ParseFrom8(&pCurrent, 2)) return E_FAIL; break; case PTP_DATATYPE_INT16: case PTP_DATATYPE_UINT16: if (!m_lValues.ParseFrom16(&pCurrent, 2)) return E_FAIL; break; case PTP_DATATYPE_INT32: case PTP_DATATYPE_UINT32: if (!m_lValues.Parse(&pCurrent, 2)) return E_FAIL; break; case PTP_DATATYPE_STRING: hr = m_cbstrValues.Init(&pCurrent, 2); if (FAILED(hr)) return hr; break; default: return E_FAIL; } m_NumValues = max(m_lValues.GetSize(), m_cbstrValues.GetSize()); } return hr; } // // This function sets the current value of a CPtpPropDesc from raw data // // Input: // pRaw -- pointer to the raw data // HRESULT CPtpPropDesc::ParseValue(BYTE *pRaw) { HRESULT hr = S_OK; BYTE *pCurrent = pRaw; switch (m_DataType) { case PTP_DATATYPE_INT8: case PTP_DATATYPE_UINT8: m_lCurrent = *pCurrent++; break; case PTP_DATATYPE_INT16: case PTP_DATATYPE_UINT16: m_lCurrent = ParseWord(&pCurrent); break; case PTP_DATATYPE_INT32: case PTP_DATATYPE_UINT32: m_lCurrent = ParseDword(&pCurrent); break; case PTP_DATATYPE_STRING: hr = m_cbstrCurrent.Init(&pCurrent, TRUE); break; default: return E_FAIL; } return hr; } // // This function writes the current value of a CPtpPropDesc to a raw buffer // // Input: // ppRaw -- pointer to pointer to a raw buffer // VOID CPtpPropDesc::WriteValue(BYTE **ppRaw) { switch (m_DataType) { case PTP_DATATYPE_INT8: case PTP_DATATYPE_UINT8: **ppRaw = (BYTE) m_lCurrent; (*ppRaw)++; break; case PTP_DATATYPE_INT16: case PTP_DATATYPE_UINT16: WriteWord(ppRaw, (WORD) m_lCurrent); break; case PTP_DATATYPE_INT32: case PTP_DATATYPE_UINT32: WriteDword(ppRaw, m_lCurrent); break; case PTP_DATATYPE_STRING: m_cbstrCurrent.WriteToBuffer(ppRaw); break; } return; } // // This function dumps the property description information to the log // VOID CPtpPropDesc::Dump() { wiauDbgDump("", "CPtpPropDesc::Dump, dumping PropDesc for property 0x%04x:", m_PropCode); wiauDbgDump("", " Data type = 0x%04x", m_DataType); wiauDbgDump("", " GetSet = 0x%02x", m_GetSet); if (m_DataType == PTP_DATATYPE_STRING) { m_cbstrDefault.Dump(" Default ="); m_cbstrCurrent.Dump(" Current ="); wiauDbgDump("", " Form flag = 0x%02x", m_FormFlag); switch (m_FormFlag) { case PTP_FORMFLAGS_RANGE: m_cbstrRangeMin.Dump(" Range min ="); m_cbstrRangeMax.Dump(" Range max ="); m_cbstrRangeStep.Dump(" Range step ="); break; case PTP_FORMFLAGS_ENUM: m_cbstrValues.Dump(" Valid values =", " "); break; default: wiauDbgDump("", " "); } } else { wiauDbgDump("", " Default = 0x%08x", m_lDefault); wiauDbgDump("", " Current = 0x%08x", m_lCurrent); wiauDbgDump("", " Form flag = 0x%02x", m_FormFlag); switch (m_FormFlag) { case PTP_FORMFLAGS_RANGE: wiauDbgDump("", " Range min = 0x%08x", m_lRangeMin); wiauDbgDump("", " Range max = 0x%08x", m_lRangeMax); wiauDbgDump("", " Range step = 0x%08x", m_lRangeStep); break; case PTP_FORMFLAGS_ENUM: m_lValues.Dump(" Valid values =", " "); break; default: wiauDbgDump("", " "); } } return; } // // This function dumps the property value to the log // VOID CPtpPropDesc::DumpValue() { wiauDbgDump("", "CPtpPropDescDumpValue, current value for property 0x%04x:", m_PropCode); if (m_DataType == PTP_DATATYPE_STRING) m_cbstrCurrent.Dump(" Current ="); else wiauDbgDump("", " Current = 0x%08x", m_lCurrent); return; }