Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1712 lines
46 KiB

/**************************************************************************
*
* (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;
}