/************************************************************************** * * (C) COPYRIGHT MICROSOFT CORP., 2001 * * TITLE: FSCam.cpp * * VERSION: 1.0 * * DATE: 15 Nov, 2000 * * DESCRIPTION: * File System Device object function implementations. * ***************************************************************************/ #include "pch.h" #include "private.h" #include "gdiplus.h" #ifdef USE_SHELLAPI #include "shlguid.h" #include "shlobj.h" #endif using namespace Gdiplus; // extern FORMAT_INFO *g_FormatInfo; // extern UINT g_NumFormatInfo; // // Constructor // FakeCamera::FakeCamera() : m_NumImages(0), m_NumItems(0), m_hFile(NULL), m_pIWiaLog(NULL), m_FormatInfo(NULL), m_NumFormatInfo(0) { } // // Destructor // FakeCamera::~FakeCamera() { if( m_pIWiaLog ) m_pIWiaLog->Release(); } ULONG FakeCamera::GetImageTypeFromFilename(WCHAR *pFilename, UINT *pFormatCode) { WCHAR *pExt; pExt = wcsrchr(pFilename, L'.'); if( pExt ) { for(UINT i=0; iFirmwareVersion = SysAllocString(L"04.18.65"); // ISSUE-8/4/2000-davepar Put properties into an INI file pDeviceInfo->PicturesTaken = m_NumImages; pDeviceInfo->PicturesRemaining = 100 - pDeviceInfo->PicturesTaken; pDeviceInfo->TotalItems = m_NumItems; GetLocalTime(&pDeviceInfo->Time); pDeviceInfo->ExposureMode = EXPOSUREMODE_MANUAL; pDeviceInfo->ExposureComp = 0; return hr; } // // Frees the item info structure // VOID FakeCamera::FreeDeviceInfo(DEVICE_INFO *pDeviceInfo) { if (pDeviceInfo) { if (pDeviceInfo->FirmwareVersion) { SysFreeString(pDeviceInfo->FirmwareVersion); pDeviceInfo->FirmwareVersion = NULL; } } } // // This function searches a directory on the hard drive for // items. // HRESULT FakeCamera::GetItemList(ITEM_HANDLE *pItemArray) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::GetItemList"); HRESULT hr = S_OK; memcpy(pItemArray, m_ItemHandles.GetData(), sizeof(ITEM_HANDLE) * m_NumItems); return hr; } // // This function searches a directory on the hard drive for // items. // // ***NOTE:*** // This function assumes that one or more attachments // associated with an image will be in the same folder // as the image. So, for example, if an image is found // in one folder and its attachment is found in a subfolder // this algorithm will not associate the image with that // attachment. This is not a serious limitation since // all cameras store their attachments in the same // folder as their image. // HRESULT FakeCamera::SearchDirEx(ITEM_HANDLE_ARRAY *pItemArray, ITEM_HANDLE ParentHandle, LPOLESTR Path) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::SearchDirEx"); HRESULT hr = S_OK; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA FindData; WCHAR TempStr[MAX_PATH]; FSUSD_FILE_DATA *pFFD_array=NULL; DWORD dwNumFilesInArray=0; DWORD dwCurArraySize=0; // // Search for everything, except ".", "..", and hidden files, put them in pFFD_array // StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, L"*"); WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SearchDirEx, searching directory %S", TempStr)); memset(&FindData, 0, sizeof(FindData)); hFind = FindFirstFile(TempStr, &FindData); if (hFind == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, empty directory %S", TempStr)); hr = S_OK; } else { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, FindFirstFile failed")); WIAS_LHRESULT(m_pIWiaLog, hr); } goto Cleanup; } pFFD_array = (FSUSD_FILE_DATA *)CoTaskMemAlloc(sizeof(FSUSD_FILE_DATA)*FFD_ALLOCATION_INCREMENT); if( !pFFD_array ) { hr = E_OUTOFMEMORY; goto Cleanup; } dwCurArraySize = FFD_ALLOCATION_INCREMENT; while (hr == S_OK) { if( wcscmp(FindData.cFileName, L".") && wcscmp(FindData.cFileName, L"..") && !(FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ) { pFFD_array[dwNumFilesInArray].dwFileAttributes = FindData.dwFileAttributes; pFFD_array[dwNumFilesInArray].ftFileTime = FindData.ftLastWriteTime; pFFD_array[dwNumFilesInArray].dwFileSize = FindData.nFileSizeLow; pFFD_array[dwNumFilesInArray].dwProcessed = 0; StringCchCopy(pFFD_array[dwNumFilesInArray].cFileName, ARRAYSIZE(pFFD_array[dwNumFilesInArray].cFileName), FindData.cFileName); dwNumFilesInArray++; if( (dwNumFilesInArray & (FFD_ALLOCATION_INCREMENT-1)) == (FFD_ALLOCATION_INCREMENT-1) ) { // Time to allocate more memory pFFD_array = (FSUSD_FILE_DATA *)CoTaskMemRealloc(pFFD_array, (sizeof(FSUSD_FILE_DATA)*(dwCurArraySize+FFD_ALLOCATION_INCREMENT))); if( !pFFD_array ) { hr = E_OUTOFMEMORY; goto Cleanup; } dwCurArraySize += FFD_ALLOCATION_INCREMENT; } } memset(&FindData, 0, sizeof(FindData)); if (!FindNextFile(hFind, &FindData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, FindNextFile failed")); WIAS_LHRESULT(m_pIWiaLog, hr); goto Cleanup; } } } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; // Now that all names under current directory are in the array, do analysis on them // 1. Find JPG images and their attachments ULONG uImageType; UINT nFormatCode; ITEM_HANDLE ImageHandle; for(DWORD i=0; i m_NumFormatInfo ) { // Something really weird happened WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Aborting SearchDirEx, Format index overflow")); hr = E_FAIL; goto Cleanup; } if( m_FormatInfo[nFormatCode].FormatGuid == WiaImgFmt_JPEG ) { // Add this item hr = CreateItemEx(ParentHandle, &(pFFD_array[i]), &ImageHandle, nFormatCode); if (FAILED(hr)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, CreateImage failed")); goto Cleanup; } if (!pItemArray->Add(ImageHandle)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, Add failed")); hr = E_OUTOFMEMORY; goto Cleanup; } pFFD_array[i].dwProcessed = 1; ImageHandle->bHasAttachments = FALSE; m_NumImages ++; StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, pFFD_array[i].cFileName); hr = SearchForAttachments(pItemArray, ImageHandle, TempStr, pFFD_array, dwNumFilesInArray); if (FAILED(hr)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, SearchForAttachments failed")); goto Cleanup; } if (hr == S_OK) { ImageHandle->bHasAttachments = TRUE; } ImageHandle->bIsFolder = FALSE; hr = S_OK; } } } // end of JPEG images and attachments // 2. For other items that are not processed. for(i=0; iAdd(ImageHandle)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, Add failed")); hr = E_OUTOFMEMORY; goto Cleanup; } StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, pFFD_array[i].cFileName); hr = SearchDirEx(pItemArray, ImageHandle, TempStr); if (FAILED(hr)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, recursive SearchDir failed")); goto Cleanup; } pFFD_array[i].dwProcessed = 1; ImageHandle->bHasAttachments = FALSE; ImageHandle->bIsFolder = TRUE; } else { // for files uImageType = GetImageTypeFromFilename(pFFD_array[i].cFileName, &nFormatCode); #ifdef GDIPLUS_CHECK if( (ITEMTYPE_IMAGE == uImageType) && !IsFormatSupportedByGDIPlus(m_FormatInfo[nFormatCode].FormatGuid)) { uImageType = ITEMTYPE_FILE; // Force to create non-image item m_FormatInfo[nFormatCode].ItemType = uImageType; m_FormatInfo[nFormatCode].FormatGuid = WiaImgFmt_UNDEFINED; } #endif hr = CreateItemEx(ParentHandle, &(pFFD_array[i]), &ImageHandle, nFormatCode); if (FAILED(hr)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, CreateImage failed")); goto Cleanup; } if (!pItemArray->Add(ImageHandle)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, Add failed")); hr = E_OUTOFMEMORY; goto Cleanup; } pFFD_array[i].dwProcessed = 1; ImageHandle->bHasAttachments = FALSE; ImageHandle->bIsFolder = FALSE; if(ITEMTYPE_IMAGE == uImageType) { m_NumImages ++; } hr = S_OK; } } hr = S_OK; Cleanup: if( hFind != INVALID_HANDLE_VALUE ) FindClose(hFind); if( pFFD_array ) CoTaskMemFree(pFFD_array); return hr; } // // Searches for attachments to an image item // inline BOOL CompareAttachmentStrings(WCHAR *pParentStr, WCHAR *pStr2) { WCHAR *pSlash = wcsrchr(pStr2, L'\\'); WCHAR *pStrTmp; if( pSlash ) pStrTmp = pSlash+1; else pStrTmp = pStr2; if( wcslen(pParentStr) == 8 && wcscmp(pParentStr+4, L"0000") > 0 && wcscmp(pParentStr+4, L"9999") < 0 ) { if( wcslen(pStrTmp) < 8 ) return FALSE; return (CSTR_EQUAL == CompareString( LOCALE_SYSTEM_DEFAULT, 0, pParentStr+4, 4, pStrTmp+4, 4) ); } else { WCHAR pStr22[MAX_PATH]; StringCchCopyW(pStr22, ARRAYSIZE(pStr22), pStrTmp); WCHAR *pDot = wcsrchr(pStr22, L'.'); if(pDot ) *pDot = L'\0'; return (CSTR_EQUAL == CompareString( LOCALE_SYSTEM_DEFAULT, 0, pParentStr, -1, pStr22, -1) ); } } HRESULT FakeCamera::SearchForAttachments(ITEM_HANDLE_ARRAY *pItemArray, ITEM_HANDLE ParentHandle, LPOLESTR Path, FSUSD_FILE_DATA *pFFD_Current, DWORD dwNumOfFiles) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::SearchForAttachments"); HRESULT hr = S_FALSE; int NumAttachments = 0; // // Attachment is defined as any non-image item whose extension is different than the parent but // the filename is the same except the first 4 letters. // WCHAR TempStrParent[MAX_PATH]; WCHAR *pTemp; pTemp = wcsrchr(Path, L'\\'); if (pTemp) { StringCchCopyW(TempStrParent, ARRAYSIZE(TempStrParent), pTemp+1); } else { StringCchCopyW(TempStrParent, ARRAYSIZE(TempStrParent), Path); } // // Chop the extension // WCHAR *pDot = wcsrchr(TempStrParent, L'.'); if (pDot) { *(pDot) = L'\0'; } else { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchForAttachments, filename did not contain a dot")); return E_INVALIDARG; } ITEM_HANDLE NonImageHandle; UINT nFormatCode; ULONG uImageType; for(DWORD i=0; iAdd(NonImageHandle)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchForAttachments, Add failed")); return E_OUTOFMEMORY; } pFFD_Current[i].dwProcessed = 1; NonImageHandle->bIsFolder = FALSE; NumAttachments++; } } } // end of FOR loop if( NumAttachments > 0 ) hr = S_OK; else hr = S_FALSE; return hr; } HRESULT FakeCamera::CreateFolderEx(ITEM_HANDLE ParentHandle, FSUSD_FILE_DATA *pFindData, ITEM_HANDLE *pFolderHandle) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::CreateFolder"); HRESULT hr = S_OK; if (!pFolderHandle) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, invalid arg")); return E_INVALIDARG; } *pFolderHandle = new ITEM_INFO; if (!*pFolderHandle) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, memory allocation failed")); return E_OUTOFMEMORY; } // // Initialize the ItemInfo structure // ITEM_INFO *pItemInfo = *pFolderHandle; memset(pItemInfo, 0, sizeof(ITEM_INFO)); // // Fill in the other item information // pItemInfo->Parent = ParentHandle; pItemInfo->pName = SysAllocString(pFindData->cFileName); memset(&pItemInfo->Time, 0, sizeof(SYSTEMTIME)); FILETIME ftLocalFileTime; FileTimeToLocalFileTime(&pFindData->ftFileTime, &ftLocalFileTime); if (!FileTimeToSystemTime(&ftLocalFileTime, &pItemInfo->Time)) WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, couldn't convert file time to system time")); pItemInfo->Format = 0; pItemInfo->bReadOnly = pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY; pItemInfo->bCanSetReadOnly = TRUE; pItemInfo->bIsFolder = TRUE; m_NumItems++; WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2, ("CreateFolder, created folder %S at 0x%08x under 0x%08x", pFindData->cFileName, pItemInfo, ParentHandle)); return hr; } HRESULT FakeCamera::CreateItemEx(ITEM_HANDLE ParentHandle, FSUSD_FILE_DATA *pFileData, ITEM_HANDLE *pItemHandle, UINT nFormatCode) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::CreateNonImage"); HRESULT hr = S_OK; if (!pItemHandle) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, invalid arg")); return E_INVALIDARG; } *pItemHandle = new ITEM_INFO; if (!*pItemHandle ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, memory allocation failed")); return E_OUTOFMEMORY; } // // The name cannot contain a dot and the name needs to be unique // wrt the parent image, so replace the dot with an underline character. // WCHAR TempStr[MAX_PATH]; StringCchCopyW(TempStr, ARRAYSIZE(TempStr), pFileData->cFileName); // // Initialize the ItemInfo structure // ITEM_INFO *pItemInfo = *pItemHandle; memset(pItemInfo, 0, sizeof(ITEM_INFO)); pItemInfo->Format = nFormatCode; if (nFormatCode) { // if known extension, it will be handled by the format code WCHAR *pDot = wcsrchr(TempStr, L'.'); if (pDot) *pDot = L'\0'; } // // Fill in the other item information // pItemInfo->Parent = ParentHandle; pItemInfo->pName = SysAllocString(TempStr); memset(&pItemInfo->Time, 0, sizeof(SYSTEMTIME)); FILETIME ftLocalFileTime; FileTimeToLocalFileTime(&pFileData->ftFileTime, &ftLocalFileTime); if (!FileTimeToSystemTime(&ftLocalFileTime, &pItemInfo->Time)) WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, couldn't convert file time to system time")); pItemInfo->Size = pFileData->dwFileSize; pItemInfo->bReadOnly = pFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY; pItemInfo->bCanSetReadOnly = TRUE; pItemInfo->bIsFolder = FALSE; m_NumItems++; WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2, ("CreateNonImage, created non-image %S at 0x%08x under 0x%08x", pFileData->cFileName, pItemInfo, ParentHandle)); return hr; } // // Construct the full path name of the item by traversing its parents // VOID FakeCamera::ConstructFullName(WCHAR *pFullName, ITEM_INFO *pItemInfo, BOOL bAddExt) { if (pItemInfo->Parent) ConstructFullName(pFullName, pItemInfo->Parent, FALSE); else StringCchCopyW(pFullName, MAX_PATH, m_RootPath); // // If this item has attachments and we're creating the name for its children, // don't add its name (it's a repeat of the child's name) // WCHAR *pTmp; if( pItemInfo->Parent && pItemInfo->Parent->bHasAttachments ) { pTmp = wcsrchr(pFullName, L'\\'); if( pTmp ) { *pTmp = L'\0'; } } StringCchCatW(pFullName, MAX_PATH, L"\\"); StringCchCatW(pFullName, MAX_PATH, pItemInfo->pName); if (bAddExt) { if( pItemInfo->Format > 0 && pItemInfo->Format < (INT)m_NumFormatInfo ) { StringCchCatW(pFullName, MAX_PATH, L"."); StringCchCatW(pFullName, MAX_PATH, m_FormatInfo[pItemInfo->Format].ExtensionString); } } } // // Frees the item info structure // VOID FakeCamera::FreeItemInfo(ITEM_INFO *pItemInfo) { if (pItemInfo) { if (pItemInfo->pName) { WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("FreeItemInfo, removing %S", pItemInfo->pName)); SysFreeString(pItemInfo->pName); pItemInfo->pName = NULL; } if (!m_ItemHandles.Remove(pItemInfo)) WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FreeItemInfo, couldn't remove handle from array")); if (m_FormatInfo[pItemInfo->Format].ItemType == ITEMTYPE_IMAGE) { m_NumImages--; } m_NumItems--; delete pItemInfo; } } // // Retrieves the thumbnail for an item // /* HRESULT FakeCamera::GetNativeThumbnail(ITEM_HANDLE ItemHandle, int *pThumbSize, BYTE **ppThumb) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::GetThumbnail"); HRESULT hr = S_OK; if (!ppThumb) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, invalid arg")); return E_INVALIDARG; } *ppThumb = NULL; *pThumbSize = 0; WCHAR FullName[MAX_PATH]; ConstructFullName(FullName, ItemHandle); BYTE *pBuffer; hr = ReadJpegHdr(FullName, &pBuffer); if (FAILED(hr) || !pBuffer) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, ReadJpegHdr failed")); return hr; } IFD ImageIfd, ThumbIfd; BOOL bSwap; hr = ReadExifJpeg(pBuffer, &ImageIfd, &ThumbIfd, &bSwap); if (FAILED(hr)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, GetExifJpegDimen failed")); delete []pBuffer; return hr; } LONG ThumbOffset = 0; for (int count = 0; count < ThumbIfd.Count; count++) { if (ThumbIfd.pEntries[count].Tag == TIFF_JPEG_DATA) { ThumbOffset = ThumbIfd.pEntries[count].Offset; } else if (ThumbIfd.pEntries[count].Tag == TIFF_JPEG_LEN) { *pThumbSize = ThumbIfd.pEntries[count].Offset; } } if (!ThumbOffset || !*pThumbSize) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, thumbnail not found")); return E_FAIL; } *ppThumb = new BYTE[*pThumbSize]; if (!*ppThumb) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, memory allocation failed")); return E_OUTOFMEMORY; } memcpy(*ppThumb, pBuffer + APP1_OFFSET + ThumbOffset, *pThumbSize); delete []pBuffer; FreeIfd(&ImageIfd); FreeIfd(&ThumbIfd); return hr; } */ HRESULT FakeCamera::CreateThumbnail(ITEM_HANDLE ItemHandle, int *pThumbSize, BYTE **ppThumb, BMP_IMAGE_INFO *pBmpImageInfo) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FSCamera::GetThumbnail"); HRESULT hr = S_OK; GpStatus Status = Gdiplus::Ok; SizeF gdipSize; BYTE *pTempBuf=NULL; CImageStream *pOutStream = NULL; Image *pImage=NULL, *pThumbnail=NULL; CLSID ClsidBmpEncoder; INT iBmpHeadSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); ITEM_INFO *pItemInfo=NULL; if (!ppThumb) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, invalid arg")); return E_INVALIDARG; } *ppThumb = NULL; *pThumbSize = 0; if( S_OK != (hr=GetClsidOfEncoder(ImageFormatBMP, &ClsidBmpEncoder))) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Cannot get Encode")); hr = E_FAIL; goto Cleanup; } WCHAR FullName[MAX_PATH]; ConstructFullName(FullName, ItemHandle); pItemInfo = (ITEM_INFO *)ItemHandle; pImage = new Image(FullName); if( !pImage || Gdiplus::ImageTypeBitmap != pImage->GetType() ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Cannot get Full GDI+ Image for %S", FullName)); hr = E_FAIL; goto Cleanup; } // Calculate Thumbnail size Status = pImage->GetPhysicalDimension(&gdipSize); if (Status != Gdiplus::Ok) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Failed in GetPhysicalDimension")); hr = E_FAIL; goto Cleanup; } if( gdipSize.Width < 1.0 || gdipSize.Height < 1.0 ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, PhysicalDimension abnormal")); hr = E_FAIL; goto Cleanup; } pItemInfo->Width = (LONG)gdipSize.Width; pItemInfo->Height = (LONG)gdipSize.Height; PixelFormat PixFmt = pImage->GetPixelFormat(); pItemInfo->Depth = (PixFmt & 0xFFFF) >> 8; // Cannot assume image is always 24bits/pixel if( (pItemInfo->Depth) < 24 ) pItemInfo->Depth = 24; pItemInfo->BitsPerChannel = 8; pItemInfo->Channels = (pItemInfo->Depth)/(pItemInfo->BitsPerChannel); if( gdipSize.Width > gdipSize.Height ) { pBmpImageInfo->Width = 120; pBmpImageInfo->Height = (INT)(gdipSize.Height*120.0/gdipSize.Width); pBmpImageInfo->Height = (pBmpImageInfo->Height + 0x3) & (~0x3); } else { pBmpImageInfo->Height = 120; pBmpImageInfo->Width = (INT)(gdipSize.Width*120.0/gdipSize.Height); pBmpImageInfo->Width = (pBmpImageInfo->Width + 0x3 ) & (~0x3); } pThumbnail = pImage->GetThumbnailImage(pBmpImageInfo->Width,pBmpImageInfo->Height); if( !pThumbnail || Gdiplus::ImageTypeBitmap != pThumbnail->GetType() ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Cannot get Thumbnail GDI+ Image")); hr = E_FAIL; goto Cleanup; } if( pImage ) { delete pImage; pImage=NULL; } #if 0 pThumbnail->Save(L"C:\\thumbdmp.bmp", &ClsidBmpEncoder, NULL); #endif // // Ask GDI+ for the image dimensions, and fill in the // passed structure // Status = pThumbnail->GetPhysicalDimension(&gdipSize); if (Status != Gdiplus::Ok) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Failed in GetPhysicalDimension")); hr = E_FAIL; goto Cleanup; } pBmpImageInfo->Width = (INT) gdipSize.Width; pBmpImageInfo->Height = (INT) gdipSize.Height; pBmpImageInfo->ByteWidth = (pBmpImageInfo->Width) << 2; pBmpImageInfo->Size = pBmpImageInfo->ByteWidth * pBmpImageInfo->Height; WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetThumbnail, W=%d H=%d", pBmpImageInfo->Width, pBmpImageInfo->Height)); if (pBmpImageInfo->Size == 0) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Thumbnail size is zero")); hr = E_FAIL; goto Cleanup; } // // See if the caller passed in a destination buffer, and make sure // it is big enough. // if (*ppThumb) { if (*pThumbSize < pBmpImageInfo->Size) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Input Buffer too small")); hr = E_INVALIDARG; goto Cleanup; } } // // Otherwise allocate memory for a buffer // else { pTempBuf = new BYTE[pBmpImageInfo->Size]; if (!pTempBuf) { hr = E_OUTOFMEMORY; goto Cleanup; } *ppThumb = pTempBuf; } // // Create output IStream // pOutStream = new CImageStream; if (!pOutStream) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = pOutStream->SetBuffer(*ppThumb, pBmpImageInfo->Size, SKIP_BOTHHDR); if (FAILED(hr)) { goto Cleanup; } // // Write the Image to the output IStream in BMP format // pThumbnail->Save(pOutStream, &ClsidBmpEncoder, NULL); // pack DWORD i, k; for(k=0, i=0; k<(DWORD)(pBmpImageInfo->Size); k+=4, i+=3) { (*ppThumb)[i] = (*ppThumb)[k]; (*ppThumb)[i+1] = (*ppThumb)[k+1]; (*ppThumb)[i+2] = (*ppThumb)[k+2]; } *pThumbSize = ((pBmpImageInfo->Size)>>2)*3; pBmpImageInfo->Size = *pThumbSize; Cleanup: if (FAILED(hr)) { if (pTempBuf) { delete []pTempBuf; pTempBuf = NULL; *ppThumb = NULL; *pThumbSize = 0; } } if (pOutStream) { pOutStream->Release(); } if( pImage ) { delete pImage; } if( pThumbnail ) { delete pThumbnail; } return hr; } PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp) { BITMAP bmp; PBITMAPINFO pbmi; WORD cClrBits; // Retrieve the bitmap's color format, width, and height. if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) { return NULL; } // Convert the color format to a count of bits. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); if (cClrBits == 1) cClrBits = 1; else if (cClrBits <= 4) cClrBits = 4; else if (cClrBits <= 8) cClrBits = 8; else if (cClrBits <= 16) cClrBits = 16; else if (cClrBits <= 24) cClrBits = 24; else cClrBits = 32; // Allocate memory for the BITMAPINFO structure. (This structure // contains a BITMAPINFOHEADER structure and an array of RGBQUAD // data structures.) if (cClrBits != 24) pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); // There is no RGBQUAD array for the 24-bit-per-pixel format. else pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); if( !pbmi ) return NULL; // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1<bmiHeader.biCompression = BI_RGB; // Compute the number of bytes in the array of color // indices and store the result in biSizeImage. // For Windows NT/2000, the width must be DWORD aligned unless // the bitmap is RLE compressed. This example shows this. // For Windows 95/98, the width must be WORD aligned unless the // bitmap is RLE compressed. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0; return pbmi; } HRESULT FakeCamera::CreateVideoThumbnail(ITEM_HANDLE ItemHandle, int *pThumbSize, BYTE **ppThumb, BMP_IMAGE_INFO *pBmpImageInfo) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FSCamera::CreateVideoThumbnail"); HRESULT hr = S_OK; HBITMAP hBmp=NULL; PBITMAPINFO pBMI=NULL; BYTE *pTempBuf=NULL; #ifdef USE_SHELLAPI IShellFolder *pDesktop=NULL; IShellFolder *pFolder=NULL; ITEMIDLIST *pidlFolder=NULL; ITEMIDLIST *pidlFile=NULL; IExtractImage *pExtract=NULL; SIZE rgSize; WCHAR *wcsTmp, wcTemp; DWORD dwPriority, dwFlags; if (!ppThumb || !pThumbSize || !pBmpImageInfo) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, invalid arg")); return E_INVALIDARG; } *ppThumb = NULL; *pThumbSize = 0; WCHAR FullName[MAX_PATH]; ConstructFullName(FullName, ItemHandle); // Calculate Thumbnail size, BUGBUG rgSize.cx = 120; rgSize.cy = 90; // Get thumbnail using Shell APIs hr = SHGetDesktopFolder(&pDesktop); if( S_OK != hr || !pDesktop ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open Desktop")); goto Cleanup; } wcsTmp = wcsrchr(FullName, L'\\'); if( wcsTmp ) { // wcTemp = *(wcsTmp+1); *(wcsTmp) = NULL; } else { hr = E_INVALIDARG; goto Cleanup; } hr = pDesktop->ParseDisplayName(NULL, NULL, FullName, NULL, &pidlFolder, NULL); if( S_OK != hr || !pidlFolder ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open IDL Folder=%S", FullName)); goto Cleanup; } hr = pDesktop->BindToObject(pidlFolder, NULL, IID_IShellFolder, (LPVOID *)&pFolder); if( S_OK != hr || !pFolder ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot bind to Folder=%S", FullName)); goto Cleanup; } // *(wcsTmp+1) = wcTemp; // restore the char hr = pFolder->ParseDisplayName(NULL, NULL, wcsTmp+1, NULL, &pidlFile, NULL); if( S_OK != hr || !pidlFile ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open IDL File=%S", wcsTmp+1)); goto Cleanup; } hr = pFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&pidlFile, IID_IExtractImage, NULL, (LPVOID *)&pExtract); if( S_OK != hr || !pExtract ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot get extract pointer=%S, hr=0x%x", wcsTmp+1, hr)); goto Cleanup; } dwFlags = 0; dwPriority=0; hr = pExtract->GetLocation(FullName, MAX_PATH, &dwPriority, &rgSize, 0, &dwFlags); if( S_OK != hr ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Failed in GetLocation")); goto Cleanup; } hr = pExtract->Extract(&hBmp); #else hBmp = (HBITMAP)LoadImage(g_hInst, MAKEINTRESOURCE(IDB_BITMAP_VIDEO), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); if( !hBmp ) { hr = HRESULT_FROM_WIN32(::GetLastError()); } #endif // end of if use ShellAPI if( S_OK != hr || !hBmp ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot extract Image hr=0x%x", hr)); goto Cleanup; } pBMI = CreateBitmapInfoStruct(hBmp); if( !pBMI ) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot create BitmapInfoStruct")); goto Cleanup; } pBmpImageInfo->Width = pBMI->bmiHeader.biWidth; pBmpImageInfo->Height = pBMI->bmiHeader.biHeight; pBmpImageInfo->ByteWidth = ((pBMI->bmiHeader.biWidth * 24 + 31 ) & ~31 ) >> 3; pBmpImageInfo->Size = pBMI->bmiHeader.biWidth * pBmpImageInfo->Height * 3; // // See if the caller passed in a destination buffer, and make sure // it is big enough. // if (*ppThumb) { if (*pThumbSize < pBmpImageInfo->Size) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Input Buffer too small")); hr = E_INVALIDARG; goto Cleanup; } } // // Otherwise allocate memory for a buffer // else { pTempBuf = new BYTE[(pBmpImageInfo->ByteWidth)*(pBmpImageInfo->Height)]; if (!pTempBuf) { hr = E_OUTOFMEMORY; goto Cleanup; } *ppThumb = pTempBuf; *pThumbSize = pBmpImageInfo->Size; } // // Create output buffer // if (!GetDIBits(GetDC(NULL), hBmp, 0, (WORD)pBMI->bmiHeader.biHeight, *ppThumb, pBMI, DIB_RGB_COLORS)) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Failed in GetDIBits")); hr = E_FAIL; goto Cleanup; } #if 0 // pack DWORD i, k; for(k=0, i=0; k<(DWORD)(pBmpImageInfo->Size); k+=4, i+=3) { pTempBuf[i] = pTempBuf[k]; pTempBuf[i+1] = pTempBuf[k+1]; pTempBuf[i+2] = pTempBuf[k+2]; } #endif Cleanup: if (FAILED(hr)) { if (pTempBuf) { delete []pTempBuf; pTempBuf = NULL; *ppThumb = NULL; *pThumbSize = 0; } } if (pBMI) LocalFree(pBMI); #ifdef USE_SHELLAPI if( pDesktop ) pDesktop->Release(); if( pFolder ) pFolder->Release(); if( pidlFolder ) CoTaskMemFree(pidlFolder); if( pidlFile ) CoTaskMemFree(pidlFile); if( pExtract ) pExtract->Release(); #endif if( hBmp ) { DeleteObject(hBmp); } return hr; } VOID FakeCamera::FreeThumbnail(BYTE *pThumb) { if (pThumb) { delete []pThumb; pThumb = NULL; } } // // Retrieves the data for an item // HRESULT FakeCamera::GetItemData(ITEM_HANDLE ItemHandle, LONG lState, BYTE *pBuf, DWORD lLength) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::GetItemData"); HRESULT hr = S_OK; if (lState & STATE_FIRST) { if (m_hFile != NULL) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, file handle is already open")); return E_FAIL; } WCHAR FullName[MAX_PATH]; ConstructFullName(FullName, ItemHandle); m_hFile = CreateFile(FullName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (m_hFile == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(::GetLastError()); WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, CreateFile failed %S", FullName)); WIAS_LHRESULT(m_pIWiaLog, hr); return hr; } } if (!(lState & STATE_CANCEL)) { DWORD Received = 0; if (!ReadFile(m_hFile, pBuf, lLength, &Received, NULL)) { hr = HRESULT_FROM_WIN32(::GetLastError()); WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, ReadFile failed")); WIAS_LHRESULT(m_pIWiaLog, hr); return hr; } if (lLength != Received) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, incorrect amount read %d", Received)); return E_FAIL; } Sleep(100); } if (lState & (STATE_LAST | STATE_CANCEL)) { CloseHandle(m_hFile); m_hFile = NULL; } return hr; } // // Deletes an item // HRESULT FakeCamera::DeleteItem(ITEM_HANDLE ItemHandle) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::DeleteItem"); HRESULT hr = S_OK; DWORD dwErr = 0; WCHAR FullName[MAX_PATH]; ConstructFullName(FullName, ItemHandle); if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(FullName) ) { dwErr = RemoveDirectory(FullName); } else { dwErr = DeleteFile(FullName); } if (!dwErr ) { hr = HRESULT_FROM_WIN32(::GetLastError()); WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("DeleteItem, DeleteFile failed %S", FullName)); WIAS_LHRESULT(m_pIWiaLog, hr); } return hr; } // // Captures a new image // HRESULT FakeCamera::TakePicture(ITEM_HANDLE *pItemHandle) { CWiaLogProc WIAS_LOGPROC(m_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "FakeCamera::TakePicture"); HRESULT hr = S_OK; if (!pItemHandle) { WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TakePicture, invalid arg")); return E_INVALIDARG; } return hr; } // // See if the camera is active // HRESULT FakeCamera::Status() { HRESULT hr = S_OK; // // This sample device is always active, but your driver should contact the // device and return S_FALSE if it's not ready. // // if (NotReady) // return S_FALSE; return hr; } // // Reset the camera // HRESULT FakeCamera::Reset() { HRESULT hr = S_OK; return hr; }