|
|
/**************************************************************************
* * (C) COPYRIGHT MICROSOFT CORP., 2000 * * TITLE: fakecam.cpp * * VERSION: 1.0 * * DATE: 18 July, 2000 * * DESCRIPTION: * Fake Camera device implementation * * TODO: Every function in this file must be changed so that it actually * talks to a real camera. * ***************************************************************************/
#include "pch.h"
//
// Globals
//
HINSTANCE g_hInst; GUID g_guidUnknownFormat;
//
// Initializes access to the camera and allocates the device info
// structure and private storage area
//
HRESULT WiaMCamInit(MCAM_DEVICE_INFO **ppDeviceInfo) { wiauDbgInit(g_hInst);
DBG_FN("WiaMCamInit");
HRESULT hr = S_OK;
//
// Locals
//
MCAM_DEVICE_INFO *pDeviceInfo = NULL; FAKECAM_DEVICE_INFO *pPrivateDeviceInfo = NULL;
REQUIRE_ARGS(!ppDeviceInfo, hr, "WiaMCamInit"); *ppDeviceInfo = NULL;
//
// Allocate the MCAM_DEVICE_INFO structure
//
pDeviceInfo = new MCAM_DEVICE_INFO; REQUIRE_ALLOC(pDeviceInfo, hr, "WiaMCamInit");
memset(pDeviceInfo, 0, sizeof(MCAM_DEVICE_INFO)); pDeviceInfo->iSize = sizeof(MCAM_DEVICE_INFO); pDeviceInfo->iMcamVersion = MCAM_VERSION; //
// Allocate the FAKECAM_DEVICE_INFO structure that the
// microdriver uses to store info
//
pPrivateDeviceInfo = new FAKECAM_DEVICE_INFO; REQUIRE_ALLOC(pPrivateDeviceInfo, hr, "WiaMCamInit");
memset(pPrivateDeviceInfo, 0, sizeof(FAKECAM_DEVICE_INFO)); pDeviceInfo->pPrivateStorage = (BYTE *) pPrivateDeviceInfo;
Cleanup: if (FAILED(hr)) { if (pDeviceInfo) { delete pDeviceInfo; pDeviceInfo = NULL; } if (pPrivateDeviceInfo) { delete pPrivateDeviceInfo; pPrivateDeviceInfo = NULL; } }
*ppDeviceInfo = pDeviceInfo;
return hr; }
//
// Frees any remaining structures held by the microdriver
//
HRESULT WiaMCamUnInit(MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("WiaMCamUnInit");
HRESULT hr = S_OK;
if (pDeviceInfo) { //
// Free anything that was dynamically allocated in the MCAM_DEVICE_INFO
// structure
//
if (pDeviceInfo->pPrivateStorage) { delete pDeviceInfo->pPrivateStorage; pDeviceInfo->pPrivateStorage = NULL; }
delete pDeviceInfo; pDeviceInfo = NULL; }
return hr; }
//
// Open a connection to the device
//
HRESULT WiaMCamOpen(MCAM_DEVICE_INFO *pDeviceInfo, PWSTR pwszPortName) { DBG_FN("WiaMCamOpen");
HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
TCHAR tszTempStr[MAX_PATH] = TEXT("");
REQUIRE_ARGS(!pDeviceInfo || !pwszPortName, hr, "WiaMCamOpen");
//
// Convert the wide port string to a tstr
//
hr = wiauStrW2T(pwszPortName, tszTempStr, sizeof(tszTempStr)); REQUIRE_SUCCESS(hr, "WiaMCamOpen", "wiauStrW2T failed");
//
// Open the camera
//
hr = FakeCamOpen(tszTempStr, pDeviceInfo); REQUIRE_SUCCESS(hr, "WiaMCamOpen", "FakeCamOpen failed"); Cleanup: return hr; }
//
// Closes the connection with the camera
//
HRESULT WiaMCamClose(MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("WiaMCamClose");
HRESULT hr = S_OK;
REQUIRE_ARGS(!pDeviceInfo, hr, "WiaMCamClose");
//
// For a real camera, CloseHandle should be called here
//
Cleanup: return hr; }
//
// Returns information about the camera, the list of items on the camera,
// and starts monitoring events from the camera
//
HRESULT WiaMCamGetDeviceInfo(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO **ppItemList) { DBG_FN("WiaMCamGetDeviceInfo"); HRESULT hr = S_OK;
//
// Locals
//
FAKECAM_DEVICE_INFO *pPrivateDeviceInfo = NULL; PTSTR ptszRootPath = NULL;
REQUIRE_ARGS(!pDeviceInfo || !ppItemList || !pDeviceInfo->pPrivateStorage, hr, "WiaMCamGetDeviceInfo"); *ppItemList = NULL;
pPrivateDeviceInfo = (UNALIGNED FAKECAM_DEVICE_INFO *) pDeviceInfo->pPrivateStorage; ptszRootPath = pPrivateDeviceInfo->tszRootPath;
//
// Build a list of all items available. The fields in the item info
// structure can either be filled in here, or for better performance
// wait until GetItemInfo is called.
//
hr = SearchDir(pPrivateDeviceInfo, NULL, ptszRootPath); REQUIRE_SUCCESS(hr, "WiaMCamGetDeviceInfo", "SearchDir failed");
//
// Fill in the MCAM_DEVICE_INFO structure
//
//
// Firmware version should be retrieved from the device, converting
// to WSTR if necessary
//
pDeviceInfo->pwszFirmwareVer = L"04.18.65";
// ISSUE-8/4/2000-davepar Put properties into an INI file
pDeviceInfo->lPicturesTaken = pPrivateDeviceInfo->iNumImages; pDeviceInfo->lPicturesRemaining = 100 - pDeviceInfo->lPicturesTaken; pDeviceInfo->lTotalItems = pPrivateDeviceInfo->iNumItems;
GetLocalTime(&pDeviceInfo->Time);
// pDeviceInfo->lExposureMode = EXPOSUREMODE_MANUAL;
// pDeviceInfo->lExposureComp = 0;
*ppItemList = pPrivateDeviceInfo->pFirstItem;
Cleanup: return hr; }
//
// Called to retrieve an event from the device
//
HRESULT WiaMCamReadEvent(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_EVENT_INFO **ppEventList) { DBG_FN("WiaMCamReadEvent"); HRESULT hr = S_OK;
return hr; }
//
// Called when events are no longer needed
//
HRESULT WiaMCamStopEvents(MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("WiaMCamStopEvents"); HRESULT hr = S_OK;
return hr; }
//
// Fill in the item info structure
//
HRESULT WiaMCamGetItemInfo(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItemInfo) { DBG_FN("WiaMCamGetItemInfo");
HRESULT hr = S_OK;
//
// This is where the driver should fill in all the fields in the
// ITEM_INFO structure. For this fake driver, the fields are filled
// in by WiaMCamGetDeviceInfo because it's easier.
//
return hr; }
//
// Frees the item info structure
//
HRESULT WiaMCamFreeItemInfo(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItemInfo) { DBG_FN("WiaMCamFreeItemInfo");
HRESULT hr = S_OK;
//
// Locals
//
FAKECAM_DEVICE_INFO *pPrivateDeviceInfo = NULL;
REQUIRE_ARGS(!pDeviceInfo || !pItemInfo || !pDeviceInfo->pPrivateStorage, hr, "WiaMCamFreeItemInfo");
if (pItemInfo->pPrivateStorage) { PTSTR ptszFullName = (PTSTR) pItemInfo->pPrivateStorage;
wiauDbgTrace("WiaMCamFreeItemInfo", "Removing %" WIAU_DEBUG_TSTR, ptszFullName);
delete []ptszFullName; ptszFullName = NULL; pItemInfo->pPrivateStorage = NULL; }
if (pItemInfo->pwszName) { delete []pItemInfo->pwszName; pItemInfo->pwszName = NULL; }
pPrivateDeviceInfo = (UNALIGNED FAKECAM_DEVICE_INFO *) pDeviceInfo->pPrivateStorage;
hr = RemoveItem(pPrivateDeviceInfo, pItemInfo); REQUIRE_SUCCESS(hr, "WiaMCamFreeItemInfo", "RemoveItem failed");
if (IsImageType(pItemInfo->pguidFormat)) { pPrivateDeviceInfo->iNumImages--; }
pPrivateDeviceInfo->iNumItems--;
delete pItemInfo; pItemInfo = NULL;
Cleanup: return hr; }
//
// Retrieves the thumbnail for an item
//
HRESULT WiaMCamGetThumbnail(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItem, int *pThumbSize, BYTE **ppThumb) { DBG_FN("WiaMCamGetThumbnail");
HRESULT hr = S_OK;
//
// Locals
//
PTSTR ptszFullName = NULL; BYTE *pBuffer = NULL; LONG ThumbOffset = 0;
REQUIRE_ARGS(!pDeviceInfo || !pItem || !pThumbSize || !ppThumb, hr, "WiaMCamGetThumbnail"); *ppThumb = NULL; *pThumbSize = 0;
ptszFullName = (PTSTR) pItem->pPrivateStorage;
hr = ReadJpegHdr(ptszFullName, &pBuffer); REQUIRE_SUCCESS(hr, "WiaMCamGetThumbnail", "ReadJpegHdr failed");
IFD ImageIfd, ThumbIfd; BOOL bSwap; hr = ReadExifJpeg(pBuffer, &ImageIfd, &ThumbIfd, &bSwap); REQUIRE_SUCCESS(hr, "WiaMCamGetThumbnail", "ReadExifJpeg failed");
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) { wiauDbgError("WiaMCamGetThumbnail", "Thumbnail not found"); hr = E_FAIL; goto Cleanup; }
*ppThumb = new BYTE[*pThumbSize]; REQUIRE_ALLOC(*ppThumb, hr, "WiaMCamGetThumbnail");
memcpy(*ppThumb, pBuffer + APP1_OFFSET + ThumbOffset, *pThumbSize);
Cleanup: if (pBuffer) { delete []pBuffer; }
FreeIfd(&ImageIfd); FreeIfd(&ThumbIfd);
return hr; }
//
// Retrieves the data for an item
//
HRESULT WiaMCamGetItemData(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItem, UINT uiState, BYTE *pBuf, DWORD dwLength) { DBG_FN("WiaMCamGetItemData"); HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
PTSTR ptszFullName = NULL; FAKECAM_DEVICE_INFO *pPrivateDeviceInfo = NULL;
REQUIRE_ARGS(!pDeviceInfo || !pItem || !pDeviceInfo->pPrivateStorage, hr, "WiaMCamGetItemData");
pPrivateDeviceInfo = (UNALIGNED FAKECAM_DEVICE_INFO *) pDeviceInfo->pPrivateStorage;
if (uiState & MCAM_STATE_FIRST) { if (pPrivateDeviceInfo->hFile != NULL) { wiauDbgError("WiaMCamGetItemData", "File handle is already open"); hr = E_FAIL; goto Cleanup; }
ptszFullName = (PTSTR) pItem->pPrivateStorage;
wiauDbgTrace("WiaMCamGetItemData", "Opening %" WIAU_DEBUG_TSTR " for reading", ptszFullName);
pPrivateDeviceInfo->hFile = CreateFile(ptszFullName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); REQUIRE_FILEHANDLE(pPrivateDeviceInfo->hFile, hr, "WiaMCamGetItemData", "CreateFile failed"); }
if (!(uiState & MCAM_STATE_CANCEL)) { DWORD dwReceived = 0;
if (!pPrivateDeviceInfo->hFile) { wiauDbgError("WiaMCamGetItemData", "File handle is NULL"); hr = E_FAIL; goto Cleanup; }
if (!pBuf) { wiauDbgError("WiaMCamGetItemData", "Data buffer is NULL"); hr = E_INVALIDARG; goto Cleanup; }
ret = ReadFile(pPrivateDeviceInfo->hFile, pBuf, dwLength, &dwReceived, NULL); REQUIRE_FILEIO(ret, hr, "WiaMCamGetItemData", "ReadFile failed");
if (dwLength != dwReceived) { wiauDbgError("WiaMCamGetItemData", "Incorrect amount read %d", dwReceived); hr = E_FAIL; goto Cleanup; }
Sleep(100); }
if (uiState & (MCAM_STATE_LAST | MCAM_STATE_CANCEL)) { if (!pPrivateDeviceInfo->hFile) { wiauDbgError("WiaMCamGetItemData", "File handle is NULL"); hr = E_FAIL; goto Cleanup; }
CloseHandle(pPrivateDeviceInfo->hFile); pPrivateDeviceInfo->hFile = NULL; }
Cleanup: return hr; }
//
// Deletes an item
//
HRESULT WiaMCamDeleteItem(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItem) { DBG_FN("WiaMCamDeleteItem"); HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
DWORD dwFileAttr = 0; PTSTR ptszFullName = NULL;
REQUIRE_ARGS(!pDeviceInfo || !pItem, hr, "WiaMCamDeleteItem");
ptszFullName = (PTSTR) pItem->pPrivateStorage;
dwFileAttr = GetFileAttributes(ptszFullName); REQUIRE_FILEIO(dwFileAttr != -1, hr, "WiaMCamDeleteItem", "GetFileAttributes failed");
dwFileAttr |= FILE_ATTRIBUTE_HIDDEN;
ret = SetFileAttributes(ptszFullName, dwFileAttr); REQUIRE_FILEIO(ret, hr, "WiaMCamDeleteItem", "SetFileAttributes failed");
wiauDbgTrace("WiaMCamDeleteItem", "File %" WIAU_DEBUG_TSTR " is now hidden", ptszFullName);
Cleanup: return hr; }
//
// Sets the protection for an item
//
HRESULT WiaMCamSetItemProt(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO *pItem, BOOL bReadOnly) { DBG_FN("WiaMCamSetItemProt"); HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
DWORD dwFileAttr = 0; PTSTR ptszFullName = NULL;
REQUIRE_ARGS(!pDeviceInfo || !pItem, hr, "WiaMCamSetItemProt");
ptszFullName = (PTSTR) pItem->pPrivateStorage;
dwFileAttr = GetFileAttributes(ptszFullName); REQUIRE_FILEIO(dwFileAttr != -1, hr, "WiaMCamSetItemProt", "GetFileAttributes failed");
if (bReadOnly) dwFileAttr |= FILE_ATTRIBUTE_READONLY; else dwFileAttr &= ~FILE_ATTRIBUTE_READONLY;
ret = SetFileAttributes(ptszFullName, dwFileAttr); REQUIRE_FILEIO(ret, hr, "WiaMCamSetItemProt", "SetFileAttributes failed");
wiauDbgTrace("WiaMCamSetItemProt", "Protection on file %" WIAU_DEBUG_TSTR " set to %d", ptszFullName, bReadOnly);
Cleanup: return hr; }
//
// Captures a new image
//
HRESULT WiaMCamTakePicture(MCAM_DEVICE_INFO *pDeviceInfo, MCAM_ITEM_INFO **ppItem) { DBG_FN("WiaMCamTakePicture"); HRESULT hr = S_OK;
REQUIRE_ARGS(!pDeviceInfo || !ppItem, hr, "WiaMCamTakePicture"); *ppItem = NULL;
Cleanup: return hr; }
//
// See if the camera is active
//
HRESULT WiaMCamStatus(MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("WiaMCamStatus");
HRESULT hr = S_OK;
REQUIRE_ARGS(!pDeviceInfo, hr, "WiaMCamStatus");
//
// 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;
Cleanup: return hr; }
//
// Reset the camera
//
HRESULT WiaMCamReset(MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("WiaMCamReset");
HRESULT hr = S_OK;
REQUIRE_ARGS(!pDeviceInfo, hr, "WiaMCamReset");
Cleanup: return hr; }
////////////////////////////////
//
// Helper functions
//
////////////////////////////////
//
// This function pretends to open a camera. A real driver
// would call CreateDevice.
//
HRESULT FakeCamOpen(PTSTR ptszPortName, MCAM_DEVICE_INFO *pDeviceInfo) { DBG_FN("FakeCamOpen");
HRESULT hr = S_OK; BOOL ret = FALSE;
//
// Locals
//
FAKECAM_DEVICE_INFO *pPrivateDeviceInfo = NULL; DWORD dwFileAttr = 0; PTSTR ptszRootPath = NULL; UINT uiRootPathSize = 0; TCHAR tszPathTemplate[] = TEXT("%userprofile%\\image");
//
// Get a pointer to the private storage, so we can put the
// directory name there
//
pPrivateDeviceInfo = (UNALIGNED FAKECAM_DEVICE_INFO *) pDeviceInfo->pPrivateStorage; ptszRootPath = pPrivateDeviceInfo->tszRootPath; uiRootPathSize = sizeof(pPrivateDeviceInfo->tszRootPath) / sizeof(pPrivateDeviceInfo->tszRootPath[0]);
//
// Unless the port name is set to something other than COMx,
// LPTx, or AUTO, use %userprofile%\image as the search directory.
// Since driver runs in LOCAL SERVICE context, %userprofile% points to profile
// of LOCAL SERVICE account, like "Documents and Settings\Local Service"
//
if (_tcsstr(ptszPortName, TEXT("COM")) || _tcsstr(ptszPortName, TEXT("LPT")) || CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, ptszPortName, -1, TEXT("AUTO"), -1) == CSTR_EQUAL) { DWORD dwResult = ExpandEnvironmentStrings(tszPathTemplate, ptszRootPath, uiRootPathSize); if (dwResult == 0 || dwResult > uiRootPathSize) { wiauDbgError("WiaMCamOpen", "ExpandEnvironmentStrings failed"); hr = E_FAIL; goto Cleanup; } } else { lstrcpyn(ptszRootPath, ptszPortName, uiRootPathSize); }
wiauDbgTrace("Open", "Image directory path is %" WIAU_DEBUG_TSTR, ptszRootPath);
dwFileAttr = GetFileAttributes(ptszRootPath); if (dwFileAttr == -1) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; ret = CreateDirectory(ptszRootPath, NULL); REQUIRE_FILEIO(ret, hr, "Open", "CreateDirectory failed"); } else { wiauDbgErrorHr(hr, "Open", "GetFileAttributes failed"); goto Cleanup; } }
Cleanup: return hr; }
//
// This function searches a directory on the hard drive for
// items.
//
HRESULT SearchDir(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pParent, PTSTR ptszPath) { DBG_FN("SearchDir");
HRESULT hr = S_OK;
//
// Locals
//
HANDLE hFind = NULL; WIN32_FIND_DATA FindData; const cchTempStrSize = MAX_PATH; TCHAR tszTempStr[cchTempStrSize] = TEXT(""); TCHAR tszFullName[MAX_PATH] = TEXT("");; MCAM_ITEM_INFO *pFolder = NULL; MCAM_ITEM_INFO *pImage = NULL; REQUIRE_ARGS(!pPrivateDeviceInfo || !ptszPath, hr, "SearchDir");
//
// Search for folders first
//
//
// Make sure search path fits into the buffer and gets zero-terminated
//
if (_sntprintf(tszTempStr, cchTempStrSize, _T("%s\\*"), ptszPath) < 0) { wiauDbgError("SearchDir", "Too long path for search"); hr = E_FAIL; goto Cleanup; } tszTempStr[cchTempStrSize - 1] = 0;
wiauDbgTrace("SearchDir", "Searching directory %" WIAU_DEBUG_TSTR, tszTempStr);
memset(&FindData, 0, sizeof(FindData)); hFind = FindFirstFile(tszTempStr, &FindData); if (hFind == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; wiauDbgWarning("SearchDir", "Directory %" WIAU_DEBUG_TSTR " is empty", tszTempStr); goto Cleanup; } else { wiauDbgErrorHr(hr, "SearchDir", "FindFirstFile failed"); goto Cleanup; } }
while (hr == S_OK) { if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (FindData.cFileName[0] != L'.')) { hr = MakeFullName(tszFullName, sizeof(tszFullName) / sizeof(tszFullName[0]), ptszPath, FindData.cFileName); REQUIRE_SUCCESS(hr, "SearchDir", "MakeFullName failed"); hr = CreateFolder(pPrivateDeviceInfo, pParent, &FindData, &pFolder, tszFullName); REQUIRE_SUCCESS(hr, "SearchDir", "CreateFolder failed");
hr = AddItem(pPrivateDeviceInfo, pFolder); REQUIRE_SUCCESS(hr, "SearchDir", "AddItem failed");
hr = SearchDir(pPrivateDeviceInfo, pFolder, tszFullName); REQUIRE_SUCCESS(hr, "SearchDir", "Recursive SearchDir failed"); }
memset(&FindData, 0, sizeof(FindData)); if (!FindNextFile(hFind, &FindData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES)) { wiauDbgErrorHr(hr, "SearchDir", "FindNextFile failed"); goto Cleanup; } } } FindClose(hFind); hr = S_OK;
//
// Search next for JPEGs
//
//
// Make sure search path fits into the buffer and gets zero-terminated
//
if (_sntprintf(tszTempStr, cchTempStrSize, _T("%s\\*.jpg"), ptszPath) < 0) { wiauDbgError("SearchDir", "Too long path for search"); hr = E_FAIL; goto Cleanup; } tszTempStr[cchTempStrSize - 1] = 0;
memset(&FindData, 0, sizeof(FindData));
hFind = FindFirstFile(tszTempStr, &FindData); if (hFind == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { hr = S_OK; wiauDbgWarning("SearchDir", "No JPEGs in directory %" WIAU_DEBUG_TSTR, tszTempStr); goto Cleanup; } else { wiauDbgErrorHr(hr, "SearchDir", "FindFirstFile failed"); goto Cleanup; } }
while (hr == S_OK) { if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) { hr = MakeFullName(tszFullName, sizeof(tszFullName) / sizeof(tszFullName[0]), ptszPath, FindData.cFileName); REQUIRE_SUCCESS(hr, "SearchDir", "MakeFullName failed");
hr = CreateImage(pPrivateDeviceInfo, pParent, &FindData, &pImage, tszFullName); REQUIRE_SUCCESS(hr, "SearchDir", "CreateImage failed");
hr = AddItem(pPrivateDeviceInfo, pImage); REQUIRE_SUCCESS(hr, "SearchDir", "AddItem failed");
hr = SearchForAttachments(pPrivateDeviceInfo, pImage, tszFullName); REQUIRE_SUCCESS(hr, "SearchDir", "SearchForAttachments failed");
if (hr == S_OK) pImage->bHasAttachments = TRUE;
hr = S_OK; }
memset(&FindData, 0, sizeof(FindData)); if (!FindNextFile(hFind, &FindData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES)) { wiauDbgErrorHr(hr, "SearchDir", "FindNextFile failed"); goto Cleanup; } } } FindClose(hFind); hr = S_OK;
//
// ISSUE-10/18/2000-davepar Do the same for other image types
//
Cleanup: return hr; }
//
// Searches for attachments to an image item
//
HRESULT SearchForAttachments(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pParent, PTSTR ptszMainItem) { DBG_FN("SearchForAttachments");
HRESULT hr = S_OK;
//
// Locals
//
INT iNumAttachments = 0; HANDLE hFind = NULL; WIN32_FIND_DATA FindData; TCHAR tszTempStr[MAX_PATH] = TEXT(""); TCHAR tszFullName[MAX_PATH] = TEXT(""); TCHAR *ptcSlash = NULL; TCHAR *ptcDot = NULL; MCAM_ITEM_INFO *pNonImage = NULL;
REQUIRE_ARGS(!pPrivateDeviceInfo || !ptszMainItem, hr, "SearchForAttachments"); //
// Find the last dot in the filename and replace the file extension with * and do the search
//
lstrcpyn(tszTempStr, ptszMainItem, sizeof(tszTempStr) / sizeof(tszTempStr[0]) - 1); ptcDot = _tcsrchr(tszTempStr, TEXT('.')); if (ptcDot) { *(ptcDot+1) = TEXT('*'); *(ptcDot+2) = TEXT('\0'); } else { wiauDbgError("SearchForAttachments", "Filename did not contain a dot"); hr = E_FAIL; goto Cleanup; }
//
// Replace the first four "free" characters of the name with ? (attachments only need to match
// the last four characters of the name)
//
ptcSlash = _tcsrchr(tszTempStr, TEXT('\\')); if (ptcSlash && ptcDot - ptcSlash > 4) { for (INT i = 1; i < 5; i++) *(ptcSlash+i) = TEXT('?'); }
memset(&FindData, 0, sizeof(FindData)); hFind = FindFirstFile(tszTempStr, &FindData); REQUIRE_FILEHANDLE(hFind, hr, "SearchForAttachments", "FindFirstFile failed");
while (hr == S_OK) { if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) && !(_tcsstr(ptszMainItem, FindData.cFileName))) { //
// Figure out the full name for the item
//
lstrcpyn(tszTempStr, ptszMainItem, sizeof(tszTempStr) / sizeof(tszTempStr[0])); ptcSlash = _tcsrchr(tszTempStr, TEXT('\\')); if (ptcSlash) { *ptcSlash = TEXT('\0'); }
hr = MakeFullName(tszFullName, sizeof(tszFullName) / sizeof(tszFullName[0]), tszTempStr, FindData.cFileName); REQUIRE_SUCCESS(hr, "SearchForAttachments", "MakeFullName failed");
hr = CreateNonImage(pPrivateDeviceInfo, pParent, &FindData, &pNonImage, tszFullName); REQUIRE_SUCCESS(hr, "SearchForAttachments", "CreateNonImage failed");
hr = AddItem(pPrivateDeviceInfo, pNonImage); REQUIRE_SUCCESS(hr, "SearchForAttachments", "AddItem failed");
iNumAttachments++; }
memset(&FindData, 0, sizeof(FindData)); if (!FindNextFile(hFind, &FindData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES)) { wiauDbgErrorHr(hr, "SearchForAttachments", "FindNextFile failed"); goto Cleanup; } } } FindClose(hFind); if (iNumAttachments > 0) hr = S_OK; else hr = S_FALSE;
Cleanup: return hr; }
HRESULT CreateFolder(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pParent, WIN32_FIND_DATA *pFindData, MCAM_ITEM_INFO **ppFolder, PTSTR ptszFullName) { DBG_FN("CreateFolder");
HRESULT hr = S_OK;
//
// Locals
//
TCHAR *ptcDot = NULL; MCAM_ITEM_INFO *pItem = NULL; TCHAR tszTempStr[MAX_PATH] = TEXT("");
REQUIRE_ARGS(!pPrivateDeviceInfo || !pFindData || !ppFolder || !ptszFullName, hr, "CreateFolder"); *ppFolder = NULL;
pItem = new MCAM_ITEM_INFO; REQUIRE_ALLOC(pItem, hr, "CreateFolder");
//
// Chop off the filename extension from the name, if it exists
//
lstrcpyn(tszTempStr, pFindData->cFileName, sizeof(tszTempStr) / sizeof(tszTempStr[0])); ptcDot = _tcsrchr(tszTempStr, TEXT('.')); if (ptcDot) *ptcDot = TEXT('\0');
//
// Fill in the MCAM_ITEM_INFO structure
//
hr = SetCommonFields(pItem, tszTempStr, ptszFullName, pFindData); REQUIRE_SUCCESS(hr, "CreateFolder", "SetCommonFields failed"); pItem->pParent = pParent; pItem->iType = WiaMCamTypeFolder;
*ppFolder = pItem;
pPrivateDeviceInfo->iNumItems++;
wiauDbgTrace("CreateFolder", "Created folder %" WIAU_DEBUG_TSTR " at 0x%08x under 0x%08x", pFindData->cFileName, pItem, pParent);
Cleanup: return hr; }
HRESULT CreateImage(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pParent, WIN32_FIND_DATA *pFindData, MCAM_ITEM_INFO **ppImage, PTSTR ptszFullName) { DBG_FN("CreateImage");
HRESULT hr = S_OK;
//
// Locals
//
PTSTR ptszDot = NULL; MCAM_ITEM_INFO *pItem = NULL; TCHAR tszTempStr[MAX_PATH] = TEXT(""); WORD width = 0; WORD height = 0;
REQUIRE_ARGS(!pPrivateDeviceInfo || !pFindData || !ppImage || !ptszFullName, hr, "CreateImage"); *ppImage = NULL;
pItem = new MCAM_ITEM_INFO; REQUIRE_ALLOC(pItem, hr, "CreateImage");
//
// Chop off the filename extension from the name, if it exists
//
lstrcpyn(tszTempStr, pFindData->cFileName, sizeof(tszTempStr) / sizeof(tszTempStr[0])); ptszDot = _tcsrchr(tszTempStr, TEXT('.')); if (ptszDot) *ptszDot = TEXT('\0');
//
// Fill in the MCAM_ITEM_INFO structure
//
hr = SetCommonFields(pItem, tszTempStr, ptszFullName, pFindData); REQUIRE_SUCCESS(hr, "CreateImage", "SetCommonFields failed"); pItem->pParent = pParent; pItem->iType = WiaMCamTypeImage; pItem->pguidFormat = &WiaImgFmt_JPEG; pItem->lSize = pFindData->nFileSizeLow; pItem->pguidThumbFormat = &WiaImgFmt_JPEG;
//
// Copy the file extension into the extension field
//
if (ptszDot) { hr = wiauStrT2W(ptszDot + 1, pItem->wszExt, MCAM_EXT_LEN * sizeof(pItem->wszExt[0])); REQUIRE_SUCCESS(hr, "CreateImage", "wiauStrT2W failed"); }
//
// Interpret the JPEG image to get the image dimensions and thumbnail size
//
hr = ReadDimFromJpeg(ptszFullName, &width, &height); REQUIRE_SUCCESS(hr, "CreateImage", "ReadDimFromJpeg failed");
pItem->lWidth = width; pItem->lHeight = height; pItem->lDepth = 24; pItem->lChannels = 3; pItem->lBitsPerChannel = 8; *ppImage = pItem;
pPrivateDeviceInfo->iNumItems++; pPrivateDeviceInfo->iNumImages++;
wiauDbgTrace("CreateImage", "Created image %" WIAU_DEBUG_TSTR " at 0x%08x under 0x%08x", pFindData->cFileName, pItem, pParent);
Cleanup: return hr; }
HRESULT CreateNonImage(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pParent, WIN32_FIND_DATA *pFindData, MCAM_ITEM_INFO **ppNonImage, PTSTR ptszFullName) { DBG_FN("CreateNonImage");
HRESULT hr = S_OK;
//
// Locals
//
PTSTR ptszDot = NULL; MCAM_ITEM_INFO *pItem = NULL; TCHAR tszTempStr[MAX_PATH] = TEXT(""); PTSTR ptszExt = NULL;
REQUIRE_ARGS(!pPrivateDeviceInfo || !pFindData || !ppNonImage || !ptszFullName, hr, "CreateNonImage"); *ppNonImage = NULL;
pItem = new MCAM_ITEM_INFO; REQUIRE_ALLOC(pItem, hr, "CreateNonImage");
//
// 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.
//
lstrcpyn(tszTempStr, pFindData->cFileName, sizeof(tszTempStr) / sizeof(tszTempStr[0])); ptszDot = _tcsrchr(tszTempStr, TEXT('.')); if (ptszDot) *ptszDot = TEXT('_');
//
// Fill in the MCAM_ITEM_INFO structure
//
hr = SetCommonFields(pItem, tszTempStr, ptszFullName, pFindData); REQUIRE_SUCCESS(hr, "CreateNonImage", "SetCommonFields failed"); pItem->pParent = pParent; pItem->iType = WiaMCamTypeOther; pItem->lSize = pFindData->nFileSizeLow;
//
// Set the format of the item based on the file extension
//
if (ptszDot) { ptszExt = ptszDot + 1;
//
// Copy the file extension into the extension field
//
hr = wiauStrT2W(ptszExt, pItem->wszExt, MCAM_EXT_LEN * sizeof(pItem->wszExt[0])); REQUIRE_SUCCESS(hr, "CreateNonImage", "wiauStrT2W failed");
if (_tcsicmp(ptszExt, TEXT("wav")) == 0) { pItem->pguidFormat = &WiaAudFmt_WAV; pItem->iType = WiaMCamTypeAudio; } else if (_tcsicmp(ptszExt, TEXT("mp3")) == 0) { pItem->pguidFormat = &WiaAudFmt_MP3; pItem->iType = WiaMCamTypeAudio; } else if (_tcsicmp(ptszExt, TEXT("wma")) == 0) { pItem->pguidFormat = &WiaAudFmt_WMA; pItem->iType = WiaMCamTypeAudio; } else if (_tcsicmp(ptszExt, TEXT("rtf")) == 0) { pItem->pguidFormat = &WiaImgFmt_RTF; pItem->iType = WiaMCamTypeOther; } else if (_tcsicmp(ptszExt, TEXT("htm")) == 0) { pItem->pguidFormat = &WiaImgFmt_HTML; pItem->iType = WiaMCamTypeOther; } else if (_tcsicmp(ptszExt, TEXT("html")) == 0) { pItem->pguidFormat = &WiaImgFmt_HTML; pItem->iType = WiaMCamTypeOther; } else if (_tcsicmp(ptszExt, TEXT("txt")) == 0) { pItem->pguidFormat = &WiaImgFmt_TXT; pItem->iType = WiaMCamTypeOther; } else if (_tcsicmp(ptszExt, TEXT("mpg")) == 0) { pItem->pguidFormat = &WiaImgFmt_MPG; pItem->iType = WiaMCamTypeVideo; } else if (_tcsicmp(ptszExt, TEXT("avi")) == 0) { pItem->pguidFormat = &WiaImgFmt_AVI; pItem->iType = WiaMCamTypeVideo; } else if (_tcsicmp(ptszExt, TEXT("asf")) == 0) { pItem->pguidFormat = &WiaImgFmt_ASF; pItem->iType = WiaMCamTypeVideo; } else if (_tcsicmp(ptszExt, TEXT("exe")) == 0) { pItem->pguidFormat = &WiaImgFmt_EXEC; pItem->iType = WiaMCamTypeOther; } else { //
// Generate a random GUID for the format
//
if (g_guidUnknownFormat.Data1 == 0) { hr = CoCreateGuid(&g_guidUnknownFormat); REQUIRE_SUCCESS(hr, "CreateNonImage", "CoCreateGuid failed"); } pItem->pguidFormat = &g_guidUnknownFormat; pItem->iType = WiaMCamTypeOther; } }
*ppNonImage = pItem;
pPrivateDeviceInfo->iNumItems++;
wiauDbgTrace("CreateNonImage", "Created non-image %" WIAU_DEBUG_TSTR " at 0x%08x under 0x%08x", pFindData->cFileName, pItem, pParent);
Cleanup: return hr; }
//
// Sets the fields of the MCAM_ITEM_INFO that are common to all items
//
HRESULT SetCommonFields(MCAM_ITEM_INFO *pItem, PTSTR ptszShortName, PTSTR ptszFullName, WIN32_FIND_DATA *pFindData) { DBG_FN("SetCommonFields");
HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
PTSTR ptszTempStr = NULL; INT iSize = 0;
REQUIRE_ARGS(!pItem || !ptszShortName || !ptszFullName || !pFindData, hr, "SetFullName");
//
// Initialize the structure
//
memset(pItem, 0, sizeof(MCAM_ITEM_INFO)); pItem->iSize = sizeof(MCAM_ITEM_INFO); iSize = lstrlen(ptszShortName) + 1; pItem->pwszName = new WCHAR[iSize]; REQUIRE_ALLOC(pItem->pwszName, hr, "SetCommonFields"); wiauStrT2W(ptszShortName, pItem->pwszName, iSize * sizeof(WCHAR)); REQUIRE_SUCCESS(hr, "SetCommonFields", "wiauStrT2W failed");
FILETIME ftLocalFileTime; memset(&pItem->Time, 0, sizeof(pItem->Time)); memset(&ftLocalFileTime, 0, sizeof(FILETIME)); ret = FileTimeToLocalFileTime(&pFindData->ftLastWriteTime, &ftLocalFileTime); REQUIRE_FILEIO(ret, hr, "SetCommonFields", "FileTimeToLocalFileTime failed"); ret = FileTimeToSystemTime(&ftLocalFileTime, &pItem->Time); REQUIRE_FILEIO(ret, hr, "SetCommonFields", "FileTimeToSystemTime failed");
pItem->bReadOnly = pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY; pItem->bCanSetReadOnly = TRUE;
//
// Set the private storage area of the MCAM_ITEM_INFO structure to the
// full path name of the item
//
iSize = lstrlen(ptszFullName) + 1; ptszTempStr = new TCHAR[iSize]; REQUIRE_ALLOC(ptszTempStr, hr, "SetCommonFields"); lstrcpy(ptszTempStr, ptszFullName); pItem->pPrivateStorage = (BYTE *) ptszTempStr;
Cleanup: return hr; }
HRESULT AddItem(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pItem) { HRESULT hr = S_OK;
REQUIRE_ARGS(!pPrivateDeviceInfo || !pItem, hr, "AddItem");
if (pPrivateDeviceInfo->pLastItem) { //
// Insert the item at the end of the list
//
pPrivateDeviceInfo->pLastItem->pNext = pItem; pItem->pPrev = pPrivateDeviceInfo->pLastItem; pItem->pNext = NULL; pPrivateDeviceInfo->pLastItem = pItem; } else { //
// List is currently empty, add this as first and only item
//
pPrivateDeviceInfo->pFirstItem = pPrivateDeviceInfo->pLastItem = pItem; pItem->pPrev = pItem->pNext = NULL; }
Cleanup: return hr; }
HRESULT RemoveItem(FAKECAM_DEVICE_INFO *pPrivateDeviceInfo, MCAM_ITEM_INFO *pItem) { HRESULT hr = S_OK;
REQUIRE_ARGS(!pPrivateDeviceInfo || !pItem, hr, "RemoveItem");
if (pItem->pPrev) pItem->pPrev->pNext = pItem->pNext; if (pItem->pNext) pItem->pNext->pPrev = pItem->pPrev;
if (pPrivateDeviceInfo->pFirstItem == pItem) pPrivateDeviceInfo->pFirstItem = pItem->pNext; if (pPrivateDeviceInfo->pLastItem == pItem) pPrivateDeviceInfo->pLastItem = pItem->pPrev;
Cleanup: return hr; }
//
// This function reads a JPEG file looking for the frame header, which contains
// the width and height of the image.
//
HRESULT ReadDimFromJpeg(PTSTR ptszFullName, WORD *pWidth, WORD *pHeight) { DBG_FN("ReadDimFromJpeg"); HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
HANDLE hFile = NULL; BYTE *pBuffer = NULL; DWORD BytesRead = 0; BYTE *pCur = NULL; int SegmentLength = 0; const int Overlap = 8; // if pCur gets within Overlap bytes of the end, read another chunk
const DWORD BytesToRead = 32 * 1024;
REQUIRE_ARGS(!ptszFullName || !pWidth || !pHeight, hr, "ReadDimFromJpeg");
*pWidth = 0; *pHeight = 0;
hFile = CreateFile(ptszFullName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); REQUIRE_FILEHANDLE(hFile, hr, "ReadDimFromJpeg", "CreateFile failed"); pBuffer = new BYTE[BytesToRead]; REQUIRE_ALLOC(pBuffer, hr, "ReadDimFromJpeg");
ret = ReadFile(hFile, pBuffer, BytesToRead, &BytesRead, NULL); REQUIRE_FILEIO(ret, hr, "ReadDimFromJpeg", "ReadFile failed");
wiauDbgTrace("ReadDimFromJpeg", "Read %d bytes", BytesRead);
pCur = pBuffer;
//
// Pretend that we read Overlap fewer bytes than were actually read
//
BytesRead -= Overlap;
while (SUCCEEDED(hr) && BytesRead != 0 && pCur[1] != 0xc0) { if (pCur[0] != 0xff) { wiauDbgError("ReadDimFromJpeg", "Not a JFIF format image"); hr = E_FAIL; goto Cleanup; }
//
// if the marker is >= 0xd0 and <= 0xd9 or is equal to 0x01
// there is no length field
//
if (((pCur[1] & 0xf0) == 0xd0 && (pCur[1] & 0x0f) < 0xa) || pCur[1] == 0x01) { SegmentLength = 0; } else { SegmentLength = ByteSwapWord(*((UNALIGNED WORD *) (pCur + 2))); }
pCur += SegmentLength + 2;
if (pCur >= pBuffer + BytesRead) { memcpy(pBuffer, pBuffer + BytesRead, Overlap);
pCur -= BytesRead;
ret = ReadFile(hFile, pBuffer + Overlap, BytesToRead - Overlap, &BytesRead, NULL); REQUIRE_FILEIO(ret, hr, "ReadDimFromJpeg", "ReadFile failed");
wiauDbgTrace("ReadDimFromJpeg", "Read %d more bytes", BytesRead); } }
if (pCur[0] != 0xff) { wiauDbgError("ReadDimFromJpeg", "Not a JFIF format image"); return E_FAIL; }
*pHeight = ByteSwapWord(*((UNALIGNED WORD *) (pCur + 5))); *pWidth = ByteSwapWord(*((UNALIGNED WORD *) (pCur + 7)));
Cleanup: if (pBuffer) { delete []pBuffer; } if (hFile && hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
return hr; }
//
// The next section contains functions useful for reading information from
// Exif files.
//
HRESULT ReadJpegHdr(PTSTR ptszFullName, BYTE **ppBuf) { DBG_FN("ReadJpegHdr"); HRESULT hr = S_OK; BOOL ret;
//
// Locals
//
HANDLE hFile = NULL; BYTE JpegHdr[] = {0xff, 0xd8, 0xff, 0xe1}; const int JpegHdrSize = sizeof(JpegHdr) + 2; BYTE tempBuf[JpegHdrSize]; DWORD BytesRead = 0; WORD TagSize = 0;
hFile = CreateFile(ptszFullName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); REQUIRE_FILEHANDLE(hFile, hr, "ReadJpegHdr", "CreateFile failed");
ret = ReadFile(hFile, tempBuf, JpegHdrSize, &BytesRead, NULL); REQUIRE_FILEIO(ret, hr, "ReadJpegHdr", "ReadFile failed"); if (BytesRead != JpegHdrSize) { wiauDbgError("ReadJpegHdr", "Wrong amount read %d", BytesRead); hr = E_FAIL; goto Cleanup; } if (memcmp(tempBuf, JpegHdr, sizeof(JpegHdr)) != 0) { wiauDbgError("ReadJpegHdr", "JPEG header not found"); hr = E_FAIL; goto Cleanup; }
TagSize = GetWord(tempBuf + sizeof(JpegHdr), TRUE); *ppBuf = new BYTE[TagSize]; REQUIRE_ALLOC(ppBuf, hr, "ReadJpegHdr");
ret = ReadFile(hFile, *ppBuf, TagSize, &BytesRead, NULL); REQUIRE_FILEIO(ret, hr, "ReadJpegHdr", "ReadFile failed"); if (BytesRead != TagSize) { wiauDbgError("ReadJpegHdr", "Wrong amount read %d", BytesRead); hr = E_FAIL; goto Cleanup; }
Cleanup: if (hFile && hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
return hr; }
HRESULT ReadExifJpeg(BYTE *pBuf, IFD *pImageIfd, IFD *pThumbIfd, BOOL *pbSwap) { DBG_FN("ReadExifJpeg"); HRESULT hr = S_OK;
BYTE ExifTag[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
if (memcmp(pBuf, ExifTag, sizeof(ExifTag)) != 0) { wiauDbgError("ReadExifJpeg", "Exif tag not found"); hr = E_FAIL; goto Cleanup; }
hr = ReadTiff(pBuf + APP1_OFFSET, pImageIfd, pThumbIfd, pbSwap); REQUIRE_SUCCESS(hr, "ReadExifJpeg", "ReadTiff failed");
Cleanup: return hr; }
HRESULT ReadTiff(BYTE *pBuf, IFD *pImageIfd, IFD *pThumbIfd, BOOL *pbSwap) { DBG_FN("ReadTiff"); HRESULT hr = S_OK;
//
// Locals
//
WORD MagicNumber = 0;
*pbSwap = FALSE;
if (pBuf[0] == 0x4d) { *pbSwap = TRUE; if (pBuf[1] != 0x4d) { wiauDbgError("ReadTiff", "Second TIFF byte swap indicator not present"); hr = E_FAIL; goto Cleanup; } } else if (pBuf[0] != 0x49 || pBuf[1] != 0x49) { wiauDbgError("ReadTiff", "TIFF byte swap indicator not present"); hr = E_FAIL; goto Cleanup; }
MagicNumber = GetWord(pBuf+2, *pbSwap); if (MagicNumber != 42) { wiauDbgError("ReadTiff", "TIFF magic number not present"); hr = E_FAIL; goto Cleanup; }
wiauDbgTrace("ReadTiff", "Reading image IFD");
pImageIfd->Offset = GetDword(pBuf + 4, *pbSwap); hr = ReadIfd(pBuf, pImageIfd, *pbSwap); REQUIRE_SUCCESS(hr, "ReadTiff", "ReadIfd failed");
wiauDbgTrace("ReadTiff", "Reading thumb IFD");
pThumbIfd->Offset = pImageIfd->NextIfdOffset; hr = ReadIfd(pBuf, pThumbIfd, *pbSwap); REQUIRE_SUCCESS(hr, "ReadTiff", "ReadIfd failed");
Cleanup: return hr; }
HRESULT ReadIfd(BYTE *pBuf, IFD *pIfd, BOOL bSwap) { DBG_FN("ReadIfd"); HRESULT hr = S_OK;
const int DIR_ENTRY_SIZE = 12; pBuf += pIfd->Offset;
pIfd->Count = GetWord(pBuf, bSwap);
pIfd->pEntries = new DIR_ENTRY[pIfd->Count]; if (!pIfd->pEntries) return E_OUTOFMEMORY;
pBuf += 2; for (int count = 0; count < pIfd->Count; count++) { pIfd->pEntries[count].Tag = GetWord(pBuf, bSwap); pIfd->pEntries[count].Type = GetWord(pBuf + 2, bSwap); pIfd->pEntries[count].Count = GetDword(pBuf + 4, bSwap); pIfd->pEntries[count].Offset = GetDword(pBuf + 8, bSwap); pBuf += DIR_ENTRY_SIZE;
wiauDbgDump("ReadIfd", "Tag 0x%04x, type %2d offset/value 0x%08x", pIfd->pEntries[count].Tag, pIfd->pEntries[count].Type, pIfd->pEntries[count].Offset); }
pIfd->NextIfdOffset = GetDword(pBuf, bSwap);
return hr; }
VOID FreeIfd(IFD *pIfd) { if (pIfd->pEntries) delete []pIfd->pEntries; pIfd->pEntries = NULL; }
WORD ByteSwapWord(WORD w) { return (w >> 8) | (w << 8); }
DWORD ByteSwapDword(DWORD dw) { return ByteSwapWord((WORD) (dw >> 16)) | (ByteSwapWord((WORD) (dw & 0xffff)) << 16); }
WORD GetWord(BYTE *pBuf, BOOL bSwap) { WORD w = *((UNALIGNED WORD *) pBuf);
if (bSwap) w = ByteSwapWord(w); return w; }
DWORD GetDword(BYTE *pBuf, BOOL bSwap) { DWORD dw = *((UNALIGNED DWORD *) pBuf);
if (bSwap) dw = ByteSwapDword(dw);
return dw; }
/*
//
// Set the default and valid values for a property
//
VOID FakeCamera::SetValidValues( INT index, CWiaPropertyList *pPropertyList ) { HRESULT hr = S_OK;
ULONG ExposureModeList[] = { EXPOSUREMODE_MANUAL, EXPOSUREMODE_AUTO, EXPOSUREMODE_APERTURE_PRIORITY, EXPOSUREMODE_SHUTTER_PRIORITY, EXPOSUREMODE_PROGRAM_CREATIVE, EXPOSUREMODE_PROGRAM_ACTION, EXPOSUREMODE_PORTRAIT };
PROPID PropId = pPropertyList->GetPropId(index); WIA_PROPERTY_INFO *pPropInfo = pPropertyList->GetWiaPropInfo(index);
//
// Based on the property ID, populate the valid values range or list information
//
switch (PropId) { case WIA_DPC_EXPOSURE_MODE: pPropInfo->ValidVal.List.Nom = EXPOSUREMODE_MANUAL; pPropInfo->ValidVal.List.cNumList = sizeof(ExposureModeList) / sizeof(ExposureModeList[0]); pPropInfo->ValidVal.List.pList = (BYTE*) ExposureModeList; break;
case WIA_DPC_EXPOSURE_COMP: pPropInfo->ValidVal.Range.Nom = 0; pPropInfo->ValidVal.Range.Min = -200; pPropInfo->ValidVal.Range.Max = 200; pPropInfo->ValidVal.Range.Inc = 50; break;
default: WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FakeCamera::SetValidValues, property 0x%08x not defined", PropId)); return; }
return; } */
/**************************************************************************\
* DllEntryPoint * * Main library entry point. Receives DLL event notification from OS. * * We are not interested in thread attaches and detaches, * so we disable thread notifications for performance reasons. * * Arguments: * * hinst - * dwReason - * lpReserved - * * Return Value: * * Returns TRUE to allow the DLL to load. * \**************************************************************************/
extern "C" __declspec( dllexport ) BOOL APIENTRY DllEntryPoint( HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: g_hInst = hinst; DisableThreadLibraryCalls(hinst); break;
case DLL_PROCESS_DETACH: break; } return TRUE; }
/**************************************************************************\
* DllCanUnloadNow * * Determines whether the DLL has any outstanding interfaces. * * Arguments: * * None * * Return Value: * * Returns S_OK if the DLL can unload, S_FALSE if it is not safe to unload. * \**************************************************************************/
extern "C" STDMETHODIMP DllCanUnloadNow(void) { return S_OK; }
|