summaryrefslogtreecommitdiff
path: root/wia/ProdScan/Validate.cpp
diff options
context:
space:
mode:
authorkarlf <[email protected]>2016-08-11 13:28:13 -0700
committerkarlf <[email protected]>2016-08-11 13:28:13 -0700
commit96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch)
treead5f3ede5cbcd6b598677ce41bcf8318471bdd92 /wia/ProdScan/Validate.cpp
parent687b274aa38fd05c8c26e3068932121876d7f745 (diff)
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'wia/ProdScan/Validate.cpp')
-rw-r--r--wia/ProdScan/Validate.cpp1994
1 files changed, 1994 insertions, 0 deletions
diff --git a/wia/ProdScan/Validate.cpp b/wia/ProdScan/Validate.cpp
new file mode 100644
index 00000000..44e20b1f
--- /dev/null
+++ b/wia/ProdScan/Validate.cpp
@@ -0,0 +1,1994 @@
+/**************************************************************************
+*
+* Copyright � Microsoft Corporation
+*
+* File Name: Validate.cpp
+*
+* Description: This file contains code for WIA property validation
+* performed by the Production Scanning Driver Sample
+* for special categories of properties such as "format"
+* and "scan region/document size" properties.
+*
+***************************************************************************/
+
+#include "stdafx.h"
+
+/**************************************************************************\
+*
+* Validates new current values for the following dependent WIA properties:
+*
+* WIA_IPA_DATATYPE (*)
+* WIA_IPS_CUR_INTENT (*)
+* WIA_IPA_DEPTH (*)
+* WIA_IPA_FORMAT
+* WIA_IPA_TYMED (skipped since its value cannot be changed for this driver)
+* WIA_IPA_COMPRESSION
+*
+* The current values for the following properties could be changed by the driver
+* when one of the above mentioned properties is changed:
+*
+* WIA_IPA_DATATYPE (*)
+* WIA_IPS_CUR_INTENT (*)
+* WIA_IPA_DEPTH (*)
+* WIA_IPA_CHANNELS_PER_PIXEL (*)
+* WIA_IPA_BITS_PER_CHANNEL (*)
+* WIA_IPA_FORMAT
+* WIA_IPA_TYMED (skipped since its value cannot be changed for this driver)
+* WIA_IPA_FILENAME_EXTENSION
+* WIA_IPA_COMPRESSION
+*
+* (*) - These properties are available only on the the Flatbed and Feeder items
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nDocumentHandlingSelect - FLAT or FEED (as defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise (E_INVALIDARG if
+* an invalid combination is attempted)
+*
+\**************************************************************************/
+
+HRESULT CWiaDriver::ValidateFormatProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nDocumentHandlingSelect)
+{
+ HRESULT hr = S_OK;
+
+ LONG lDataType = WIA_DATA_COLOR;
+ LONG lIntent = WIA_INTENT_NONE;
+ LONG lDepth = 24;
+ LONG lChannelsPerPixel = 3;
+ LONG lBitsPerChannel = 8;
+ GUID guidFormat = WiaImgFmt_UNDEFINED;
+ LONG lCompression = WIA_COMPRESSION_NONE;
+ BSTR bstrFileExtension = NULL;
+ BYTE bRawBitsPerChannel[3] = {};
+
+ BOOL bDataTypeChanged = FALSE;
+ BOOL bIntentChanged = FALSE;
+ BOOL bImageTypeIntentChanged = FALSE;
+ BOOL bDepthChanged = FALSE;
+ BOOL bFormatChanged = FALSE;
+ BOOL bCompressionChanged = FALSE;
+
+ PROPSPEC ps[3] = {};
+ ULONG nPropSpec = 0;
+
+ if ((!pWiasContext) || (!pPropertyContext))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameters, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // Check which color properties have been changed (ignore failures).
+ // Note that the Auto item supports only format, tymed and compression:
+ //
+ if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect))
+ {
+ wiasIsPropChanged(WIA_IPA_DATATYPE, pPropertyContext, &bDataTypeChanged);
+ wiasIsPropChanged(WIA_IPS_CUR_INTENT, pPropertyContext, &bIntentChanged);
+ wiasIsPropChanged(WIA_IPA_DEPTH, pPropertyContext, &bDepthChanged);
+ }
+ wiasIsPropChanged(WIA_IPA_FORMAT, pPropertyContext, &bFormatChanged);
+ wiasIsPropChanged(WIA_IPA_COMPRESSION, pPropertyContext, &bCompressionChanged);
+
+ if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect))
+ {
+ //
+ // Read the current WIA_IPS_CUR_INTENT value:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_CUR_INTENT, &lIntent, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_CUR_INTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // When the intent is changed check if an image type intent flag is set:
+ //
+ if (SUCCEEDED(hr))
+ {
+ bImageTypeIntentChanged = (BOOL)(bIntentChanged && (WIA_INTENT_IMAGE_TYPE_MASK & lIntent));
+ }
+ }
+ }
+
+ //
+ // Read the other current property values (no matter if each respective property was changed or not):
+ //
+
+ if (SUCCEEDED(hr) && (bDataTypeChanged || bIntentChanged || bDepthChanged) &&
+ ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect)))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPA_DATATYPE, &lDataType, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_DATATYPE, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPA_DEPTH, &lDepth, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_DEPTH, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr) && (bFormatChanged || bCompressionChanged))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPA_COMPRESSION, &lCompression, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_COMPRESSION, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropGuid(pWiasContext, WIA_IPA_FORMAT, &guidFormat, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_FORMAT, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ //
+ // If the application changed the image type intent the driver must consider
+ // that WIA_IPA_DATA_TYPE was changed to the value apropriate for the new
+ // intent no matter if the application set WIA_IPA_DATA_TYPE and to what value:
+ //
+ if (SUCCEEDED(hr) && bImageTypeIntentChanged)
+ {
+ //
+ // If multiple color intents are set at the same time consider
+ // just one and give the highest priority to highest bitdepth:
+ //
+ if (WIA_INTENT_IMAGE_TYPE_COLOR & lIntent)
+ {
+ bDataTypeChanged = TRUE;
+ lDataType = WIA_DATA_COLOR;
+ }
+ else if (WIA_INTENT_IMAGE_TYPE_GRAYSCALE & lIntent)
+ {
+ bDataTypeChanged = TRUE;
+ lDataType = WIA_DATA_GRAYSCALE;
+ }
+ }
+
+ //
+ // Validate the new current values against the total supported values for
+ // each of the changed properties with write access in this category:
+ //
+ // WIA_IPA_DATATYPE
+ // WIA_IPS_CUR_INTENT
+ // WIA_IPA_DEPTH
+ // WIA_IPA_FORMAT
+ // WIA_IPA_TYMED (skipped here since its value cannot be changed for this driver)
+ // WIA_IPA_COMPRESSION
+ //
+ // This sample driver can validate color and format properties separately
+ // since none of its color modes (WIA_IPA_DATATYPE and WIA_IPA_DEPTH
+ // combinations) are dependent on format changes (WIA_IPA_FORMAT,
+ // WIA_IPA_TYMED -ignored here- and WIA_IPA_COMPRESSION combinations).
+ // If the driver would also support WIA_DATA_BW, WIA_COMPRESSION_G4
+ // and WiaImgFmt_TIFF the driver would need to validate all the color
+ // and format properties together (for example WIA_DATA_BW and
+ // WIA_COMPRESSION_G4 do neither work with WiaImgFmt_EXIF).
+ //
+ if (SUCCEEDED(hr) && ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect)) &&
+ (bDataTypeChanged || bIntentChanged || bDepthChanged))
+ {
+ nPropSpec = 0;
+
+ if (bDataTypeChanged)
+ {
+ ps[nPropSpec].ulKind = PRSPEC_PROPID;
+ ps[nPropSpec].propid = WIA_IPA_DATATYPE;
+ nPropSpec++;
+ }
+
+ if (bIntentChanged)
+ {
+ ps[nPropSpec].ulKind = PRSPEC_PROPID;
+ ps[nPropSpec].propid = WIA_IPS_CUR_INTENT;
+ nPropSpec++;
+ }
+
+ if (bDepthChanged)
+ {
+ ps[nPropSpec].ulKind = PRSPEC_PROPID;
+ ps[nPropSpec].propid = WIA_IPA_DEPTH;
+ nPropSpec++;
+ }
+
+ hr = wiasValidateItemProperties(pWiasContext, nPropSpec, ps);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Invalid color property value(s) requested, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr) && (bFormatChanged || bCompressionChanged))
+ {
+ nPropSpec = 0;
+
+ if (bFormatChanged)
+ {
+ ps[nPropSpec].ulKind = PRSPEC_PROPID;
+ ps[nPropSpec].propid = WIA_IPA_FORMAT;
+ nPropSpec++;
+ }
+
+ if (bCompressionChanged)
+ {
+ ps[nPropSpec].ulKind = PRSPEC_PROPID;
+ ps[nPropSpec].propid = WIA_IPA_COMPRESSION;
+ nPropSpec++;
+ }
+
+ hr = wiasValidateItemProperties(pWiasContext, nPropSpec, ps);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Invalid format property value(s) requested, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Additional validation for WIA_IPA_DATATYPE and WIA_IPA_DEPTH:
+ //
+ if (SUCCEEDED(hr) && ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect)) &&
+ (bDataTypeChanged || bDepthChanged))
+ {
+ if (bDataTypeChanged && bDepthChanged)
+ {
+ if (((WIA_DATA_COLOR == lDataType) && (8 == lDepth)) ||
+ ((WIA_DATA_GRAYSCALE == lDataType) && (24 == lDepth)))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Unsupported data type (%u) - depth (%u) combination requested, hr = 0x%08X",
+ lDataType, lDepth, hr));
+ }
+ }
+ else if (bDataTypeChanged && (!bDepthChanged))
+ {
+ if (WIA_DATA_COLOR == lDataType)
+ {
+ lDepth = 24;
+ }
+ else if (WIA_DATA_GRAYSCALE == lDataType)
+ {
+ lDepth = 8;
+ }
+ else if (WIA_DATA_AUTO == lDataType)
+ {
+ lDepth = WIA_DEPTH_AUTO;
+ }
+ }
+ else if ((!bDataTypeChanged) && bDepthChanged)
+ {
+ if (8 == lDepth)
+ {
+ lDataType = WIA_DATA_GRAYSCALE;
+ }
+ else if (24 == lDepth)
+ {
+ lDataType = WIA_DATA_COLOR;
+ }
+ else if (WIA_DEPTH_AUTO == lDepth)
+ {
+ lDataType = WIA_DATA_AUTO;
+ }
+ }
+ }
+
+ //
+ // Additional validation for WIA_IPA_FORMAT and WIA_IPA_COMPRESSION (skipped for the
+ // sample non-image sources since those do not support compresssed data transfers):
+ //
+ if (SUCCEEDED(hr) && ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect) ||
+ (AUTO_SOURCE == nDocumentHandlingSelect)) && (bFormatChanged || bCompressionChanged))
+ {
+ if (bFormatChanged && (!bCompressionChanged))
+ {
+ //
+ // If WIA_IPA_FORMAT if changed alone, update WIA_IPA_COMPRESSION to match:
+ //
+ if (IsEqualGUID(guidFormat, WiaImgFmt_EXIF))
+ {
+ lCompression = WIA_COMPRESSION_JPEG;
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_BMP) || IsEqualGUID(guidFormat, WiaImgFmt_RAW))
+ {
+ lCompression = WIA_COMPRESSION_NONE;
+ }
+ }
+ else if ((!bFormatChanged) && bCompressionChanged)
+ {
+ //
+ // If WIA_IPA_COMPRESSION if changed alone, update WIA_IPA_FORMAT to match:
+ //
+ if ((WIA_COMPRESSION_JPEG == lCompression) || (WIA_COMPRESSION_AUTO == lCompression))
+ {
+ guidFormat = WiaImgFmt_EXIF;
+ }
+ else if (WIA_COMPRESSION_NONE == lCompression)
+ {
+ guidFormat = WiaImgFmt_BMP;
+ }
+ }
+ else if (bFormatChanged && bCompressionChanged)
+ {
+ //
+ // If both WIA_IPA_FORMAT and WIA_IPA_COMPRESSION are changed, verify that their values work together:
+ //
+ if (((WIA_COMPRESSION_NONE == lCompression) && IsEqualGUID(guidFormat, WiaImgFmt_EXIF)) ||
+ (((WIA_COMPRESSION_JPEG == lCompression) || (WIA_COMPRESSION_AUTO == lCompression)) &&
+ (IsEqualGUID(guidFormat, WiaImgFmt_BMP) || IsEqualGUID(guidFormat, WiaImgFmt_RAW))))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Unsupported file format - compression mode combination, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ //
+ // Update current values:
+ //
+
+ if (SUCCEEDED(hr) && ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect)) &&
+ (bDataTypeChanged || bIntentChanged || bDepthChanged))
+ {
+ //
+ // WIA_IPA_DATATYPE:
+ //
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_DATATYPE, lDataType);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_DATATYPE, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_DATATYPE, pPropertyContext, TRUE);
+ }
+
+ //
+ // WIA_IPS_CUR_INTENT
+ //
+ // If an image type intent is set we must make sure it matches the current WIA_IPA_DATATYPE.
+ // Don't do anything if the application changes any of the other intent flags.
+ //
+ if (SUCCEEDED(hr) && (lIntent & WIA_INTENT_IMAGE_TYPE_MASK))
+ {
+ //
+ // Reset all current image type intent flags.
+ //
+ lIntent &= ~ WIA_INTENT_IMAGE_TYPE_MASK;
+
+ //
+ // .. and add just the one apropriate with the current WIA_IPA_DATATYPE value:
+ //
+
+ switch (lDataType)
+ {
+ case WIA_DATA_COLOR:
+ lIntent |= WIA_INTENT_IMAGE_TYPE_COLOR;
+ break;
+
+ case WIA_DATA_GRAYSCALE:
+ lIntent |= WIA_INTENT_IMAGE_TYPE_GRAYSCALE;
+ }
+
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_CUR_INTENT, lIntent);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_CUR_INTENT, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPS_CUR_INTENT, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_DEPTH:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_DEPTH, lDepth);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_DEPTH, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_DEPTH, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_CHANNELS_PER_PIXEL:
+ //
+ if (SUCCEEDED(hr))
+ {
+ lChannelsPerPixel = (24 == lDepth) ? 3 : 1;
+
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_CHANNELS_PER_PIXEL, lChannelsPerPixel);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_CHANNELS_PER_PIXEL, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_CHANNELS_PER_PIXEL, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_BITS_PER_CHANNEL:
+ //
+ if (SUCCEEDED(hr))
+ {
+ lBitsPerChannel = 8;
+
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_BITS_PER_CHANNEL, lBitsPerChannel);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_BITS_PER_CHANNEL, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_BITS_PER_CHANNEL, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_RAW_BITS_PER_CHANNEL
+ //
+ if (SUCCEEDED(hr))
+ {
+ for (int i = 0; i < lChannelsPerPixel; i++)
+ {
+ bRawBitsPerChannel[i] = 8;
+ }
+
+ hr = wiasWritePropBin(pWiasContext, WIA_IPA_RAW_BITS_PER_CHANNEL, lChannelsPerPixel, bRawBitsPerChannel);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_RAW_BITS_PER_CHANNEL, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_RAW_BITS_PER_CHANNEL, pPropertyContext, TRUE);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr) && (bFormatChanged || bCompressionChanged))
+ {
+ //
+ // WIA_IPA_COMPRESSION:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_COMPRESSION, lCompression);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_COMPRESSION, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_COMPRESSION, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_FORMAT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropGuid(pWiasContext, WIA_IPA_FORMAT, guidFormat);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_FORMAT, hr = 0x%08X", hr));
+ }
+ else
+ {
+ wiasSetPropChanged(WIA_IPA_COMPRESSION, pPropertyContext, TRUE);
+ }
+ }
+
+ //
+ // WIA_IPA_FILENAME_EXTENSION:
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ if (IsEqualGUID(guidFormat, WiaImgFmt_BMP))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_BMP);
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_EXIF))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_JPG);
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_RAW) || IsEqualGUID(guidFormat, WiaImgFmt_RAWBAR) ||
+ IsEqualGUID(guidFormat, WiaImgFmt_RAWPAT) || IsEqualGUID(guidFormat, WiaImgFmt_RAWMIC))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_RAW);
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_CSV))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_CSV);
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_TXT))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_TXT);
+ }
+ else if (IsEqualGUID(guidFormat, WiaImgFmt_XMLBAR) || IsEqualGUID(guidFormat, WiaImgFmt_XMLPAT) ||
+ IsEqualGUID(guidFormat, WiaImgFmt_XMLMIC))
+ {
+ bstrFileExtension = SysAllocString(FILE_EXT_XML);
+ }
+ else
+ {
+ hr = E_FAIL;
+ WIAEX_ERROR((g_hInst, "Unsupported file format, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr) && (!bstrFileExtension))
+ {
+ hr = E_OUTOFMEMORY;
+ WIAEX_ERROR((g_hInst, "Unable to allocate memory for new file extension, hr = 0x%08X", hr));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropStr(pWiasContext, WIA_IPA_FILENAME_EXTENSION, bstrFileExtension);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_FILENAME_EXTENSION, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ if (bstrFileExtension)
+ {
+ SysFreeString(bstrFileExtension);
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Updates the following "image information" properties:
+*
+* WIA_IPA_PIXELS_PER_LINE
+* WIA_IPA_NUMBER_OF_LINES
+* WIA_IPA_BYTES_PER_LINE
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nDocumentHandlingSelect - FLAT or FEED (as defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateImageInfoProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nDocumentHandlingSelect)
+{
+ HRESULT hr = S_OK;
+ LONG lXExtent = 0;
+ LONG lYExtent = 0;
+ LONG lPixelsPerLine = 0;
+ LONG lNumberOfLines = 0;
+ LONG lDepth = 0;
+ LONG lBytesPerLine = 0;
+
+ if ((!pWiasContext) || (!pPropertyContext) || (AUTO_SOURCE == nDocumentHandlingSelect))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameters, hr = 0x%08X", hr));
+ }
+
+ //
+ // Read the current extent and bit depth values:
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPA_DEPTH, &lDepth, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_DEPTH, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_XEXTENT, &lXExtent, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_XEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_YEXTENT, &lYExtent, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_YEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // WIA_IPA_PIXELS_PER_LINE - the image width, in pixels, for the final image
+ // WIA_IPA_NUMBER_OF_LINES - the image length, in pixels, for the final image
+ // WIA_IPA_BYTES_PER_LINE - line width in bytes matching WIA_IPA_PIXELS_PER_LINE and WIA_IPA_DEPTH
+ //
+
+ lPixelsPerLine = lXExtent;
+ lNumberOfLines = lYExtent;
+ lBytesPerLine = BytesPerLine(lPixelsPerLine, lDepth);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_PIXELS_PER_LINE, lPixelsPerLine);
+
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_PIXELS_PER_LINE, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_NUMBER_OF_LINES, lNumberOfLines);
+
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_NUMBER_OF_LINES, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPA_BYTES_PER_LINE, lBytesPerLine);
+
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPA_BYTES_PER_LINE, hr = 0x%08X", hr));
+ }
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Validates new current values for the following dependent WIA properties:
+*
+* WIA_IPS_PAGE_SIZE
+* WIA_IPS_ORIENTATION
+* WIA_IPS_PAGE_WIDTH
+* WIA_IPS_PAGE_HEIGHT
+* WIA_IPS_XPOS
+* WIA_IPS_YPOS
+* WIA_IPS_XEXTENT
+* WIA_IPS_YEXTENT
+* WIA_IPS_XRES
+* WIA_IPS_YRES
+* WIA_IPS_XSCALING
+* WIA_IPS_YSCALING
+* WIA_IPS_LONG_DOCUMENT
+*
+* If the application changes the document size and orientation the driver
+* should update the current and valid origin and extent properties to match
+* at the current resolution the current full document dimensions.
+*
+* Resolution changes should also cause updated origins and extents (valid and current).
+*
+* Orientation changes should result in updated valid page size lists and
+* updated current and valid origin and extents values.
+*
+* The driver is going to consider the origins and extents to configure
+* the scan area (crop region) and the current page size to configure
+* the physical document size, if needed.
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nDocumentHandlingSelect - FLAT or FEED (as defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise (E_INVALIDARG if
+* an invalid combination is attempted)
+*
+\**************************************************************************/
+
+HRESULT CWiaDriver::ValidateRegionProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nDocumentHandlingSelect)
+{
+ HRESULT hr = S_OK;
+
+ if ((!pWiasContext) || (!pPropertyContext) || (AUTO_SOURCE == nDocumentHandlingSelect))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameters, hr = 0x%08X", hr));
+ }
+
+ LONG lXRes = 0;
+ LONG lYRes = 0;
+ LONG lMinXExtent = (MIN_SCAN_AREA_WIDTH * OPTICAL_RESOLUTION) / 1000;
+ LONG lMinYExtent = (MIN_SCAN_AREA_HEIGHT * OPTICAL_RESOLUTION) / 1000;
+ LONG lMaxXExtent = (MAX_SCAN_AREA_WIDTH * OPTICAL_RESOLUTION) / 1000;
+ LONG lMaxYExtent = (MAX_SCAN_AREA_HEIGHT * OPTICAL_RESOLUTION) / 1000;
+
+ LONG lXPos = 0;
+ LONG lYPos = 0;
+ LONG lXExtent = lMaxXExtent;
+ LONG lYExtent = lMaxYExtent;
+
+ LONG lPageWidth = MAX_SCAN_AREA_WIDTH;
+ LONG lPageHeight = MAX_SCAN_AREA_HEIGHT;
+ LONG lPageSize = WIA_PAGE_LETTER;
+ LONG lOrientation = PORTRAIT;
+ LONG lMaxWidth = MAX_SCAN_AREA_WIDTH;
+ LONG lMaxHeight = MAX_SCAN_AREA_HEIGHT;
+ LONG lLongDocument = WIA_LONG_DOCUMENT_DISABLED;
+
+ BOOL bPageSizeChanged = FALSE;
+ BOOL bOrientationChanged = FALSE;
+ BOOL bLongDocumentChanged = FALSE;
+
+ //
+ // Read the current property values (no matter if they were changed or not):
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_XPOS, &lXPos, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_XPOS, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_YPOS, &lYPos, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_YPOS, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_XEXTENT, &lXExtent, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_XEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_YEXTENT, &lYExtent, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_YEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_XRES, &lXRes, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_XRES, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_YRES, &lYRes, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_YRES, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // In order to validate scan frame or resolution changes we must know
+ // the maximum scan area size. For Flatbed this is the total bed size.
+ // For Feeder this is the size of the currently selected document size.
+ //
+ if (SUCCEEDED(hr) &&(FEED == nDocumentHandlingSelect))
+ {
+ wiasIsPropChanged(WIA_IPS_PAGE_SIZE, pPropertyContext, &bPageSizeChanged);
+ wiasIsPropChanged(WIA_IPS_ORIENTATION, pPropertyContext, &bOrientationChanged);
+ wiasIsPropChanged(WIA_IPS_LONG_DOCUMENT, pPropertyContext, &bLongDocumentChanged);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_ORIENTATION, &lOrientation, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_ORIENTATION, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_PAGE_SIZE, &lPageSize, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_PAGE_SIZE, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_LONG_DOCUMENT, &lLongDocument, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_LONG_DOCUMENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // When WIA_LONG_DOCUMENT_ENABLED is set, if the application is not doing this update,
+ // the driver must update itself the current WIA_IPS_PAGE_SIZE property value to WIA_PAGE_AUTO.
+ // If WIA_LONG_DOCUMENT_ENABLED is set and the application changes WIA_IPS_PAGE_SIZE to
+ // another value than WIA_PAGE_AUTO, the driver must self-update the WIA_IPS_LONG_DOCUMENT
+ // property to WIA_LONG_DOCUMENT_DISABLED.
+ //
+ if (SUCCEEDED(hr) && (bPageSizeChanged || bLongDocumentChanged))
+ {
+ if ((WIA_PAGE_AUTO != lPageSize) && (WIA_LONG_DOCUMENT_ENABLED == lLongDocument))
+ {
+ if (bLongDocumentChanged && bPageSizeChanged)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid WIA_IPS_PAGE_SIZE value for WIA_LONG_DOCUMENT_ENABLED, hr = 0x%08X", hr));
+ }
+ else if (bLongDocumentChanged && (!bPageSizeChanged))
+ {
+ lPageSize = WIA_PAGE_AUTO;
+ bPageSizeChanged = TRUE;
+ }
+ else if ((!bLongDocumentChanged) && bPageSizeChanged)
+ {
+ lLongDocument = WIA_LONG_DOCUMENT_DISABLED;
+ bLongDocumentChanged = TRUE;
+ }
+ }
+ }
+
+ //
+ // Validate the current WIA_IPS_PAGE_SIZE against the valid values
+ // apropriate with the current WIA_IPS_ORIENTATION:
+ //
+ if (SUCCEEDED(hr) && (bPageSizeChanged || bOrientationChanged))
+ {
+ CBasicDynamicArray<LONG> &lPageSizesArray = (PORTRAIT == lOrientation) ? m_lPortraitSizesArray : m_lLandscapeSizesArray;
+
+ if (-1 == lPageSizesArray.Find(lPageSize))
+ {
+ if (bPageSizeChanged)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid WIA_IPS_PAGE_SIZE value, hr = 0x%08X", hr));
+ }
+ else if (WIA_PAGE_AUTO != lPageSize)
+ {
+ //
+ // This means that the application did not request the page size
+ // to be changed, just changed the orientation and the current
+ // page size is not supported in the new orientation so we should
+ // quietly select WIA_PAGE_CUSTOM:
+ //
+ lPageSize = WIA_PAGE_CUSTOM;
+ lPageWidth = lMaxWidth;
+ lPageHeight = lMaxHeight;
+ bPageSizeChanged = TRUE;
+ }
+ }
+ else
+ {
+ //
+ // For WIA_PAGE_CUSTOM the page dimensions are the maximum dimensions of the scan area,
+ // same for WIA_PAGE_AUTO (real page dimensions being detected here only after the
+ // document has been scanned and reflected in the final image layout and dimensions):
+ //
+ if ((WIA_PAGE_CUSTOM == lPageSize) || (WIA_PAGE_AUTO == lPageSize))
+ {
+ lPageWidth = lMaxWidth;
+ lPageHeight = lMaxHeight;
+ }
+ else
+ {
+ //
+ // The page sizes from the current array are guaranteed to fit in
+ // the total scan acquisition area limits, minimum and maximum:
+ //
+ hr = GetPageDimensions(lPageSize, (BOOL)(PORTRAIT == lOrientation), lPageWidth, lPageHeight);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Unable to retrieve dimensions for the current document size, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ //
+ // For Feeder the actual maximum dimensions for the scan area
+ // are dictated by the current document size selected:
+ //
+ if (SUCCEEDED(hr))
+ {
+ lMaxWidth = lPageWidth;
+ lMaxHeight = lPageHeight;
+ }
+ }
+ }
+
+ //
+ // Use wiasUpdateScanRect to validate the current extents and
+ // resolutions and update all their dependent properties:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasUpdateScanRect(pWiasContext, pPropertyContext, lMaxWidth, lMaxHeight);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "wiasUpdateScanRect(max width = %u, max height = %u) failed, hr = 0x%08X", lMaxWidth, lMaxHeight, hr));
+ }
+ }
+
+ //
+ // For feeder special validation must be performed for WIA_IPS_ORIENTATION and WIA_IPS_PAGE_SIZE changes:
+ //
+ if (FEED == nDocumentHandlingSelect)
+ {
+ //
+ // Update valid list of values for WIA_IPS_PAGE_SIZE according with the new set WIA_IPS_ORIENTATION:
+ //
+ if (SUCCEEDED(hr) && bOrientationChanged)
+ {
+ LONG lNumPageSizes = 0;
+ CBasicDynamicArray<LONG> &lPageSizesArray = (PORTRAIT == lOrientation) ? m_lPortraitSizesArray : m_lLandscapeSizesArray;
+ lNumPageSizes = lPageSizesArray.Size();
+
+ hr = wiasSetValidListLong(pWiasContext, WIA_IPS_PAGE_SIZE, (ULONG)lNumPageSizes,
+ lPageSize, (LONG *)lPageSizesArray.Array());
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_PAGE_SIZE values, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // If the current WIA_IPS_PAGE_SIZE is changed updated all the dependent properties:
+ //
+ if (SUCCEEDED(hr) && bPageSizeChanged)
+ {
+ //
+ // Update current WIA_IPS_PAGE_SIZE value:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_PAGE_SIZE, lPageSize);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_PAGE_SIZE, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Update current WIA_IPS_PAGE_WIDTH:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_PAGE_WIDTH, lPageWidth);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_PAGE_WIDTH, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Update current WIA_IPS_LONG_DOCUMENT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_LONG_DOCUMENT, lLongDocument);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_PAGE_HEIGHT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Update current WIA_IPS_PAGE_HEIGHT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_PAGE_HEIGHT, lPageHeight);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_PAGE_HEIGHT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // If the current page size is changed always update the current and valid
+ // WIA_IPS_XPOS, WIA_IPS_YPOS, WIA_IPS_XEXTENT and WIA_IPS_YEXTENT to match
+ // the entire area of the currently selected document size, overwriting any
+ // direct change for any of these properties requested at the same time with
+ // the change for WIA_IPS_ORIENTATION or WIA_IPS_PAGESIZE.
+ //
+
+ //
+ // Read current WIA_IPS_XRES:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_XRES, &lXRes, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_XRES, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Read current WIA_IPS_YRES:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_YRES, &lYRes, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_YRES, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Compute the new extent limits:
+ //
+ if (SUCCEEDED(hr))
+ {
+ lMinXExtent = (MIN_SCAN_AREA_WIDTH * lXRes) / 1000;
+ if (!lMinXExtent)
+ {
+ lMinXExtent = 1;
+ }
+ lMinYExtent = (MIN_SCAN_AREA_HEIGHT * lYRes) / 1000;
+ if (!lMinYExtent)
+ {
+ lMinYExtent = 1;
+ }
+ lMaxXExtent = (lPageWidth * lXRes) / 1000;
+ lMaxYExtent = (lPageHeight * lYRes) / 1000;
+
+ if ((lMaxXExtent < 1) || (lMaxYExtent < 1) || (lMinXExtent > lMaxXExtent) || (lMinYExtent > lMaxYExtent))
+ {
+ hr = E_FAIL;
+ WIAEX_ERROR((g_hInst, "Unable to update the extent limits to match the new document size, hr = 0x%08X", hr));
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // The new current scan region, covering the entire document size:
+ //
+ lXPos = 0;
+ lYPos = 0;
+ lXExtent = lMaxXExtent;
+ lYExtent = lMaxYExtent;
+
+ //
+ // Set new valid values for WIA_IPS_XPOS:
+ //
+ hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_XPOS, 0, lXPos, lMaxXExtent - lMinXExtent, 1);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_XPOS, hr = 0x%08X", hr));
+ }
+
+ //
+ // Set new valid values for WIA_IPS_YPOS:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_YPOS, 0, lYPos, lMaxYExtent - lMinYExtent, 1);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_YPOS, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new valid values for WIA_IPS_XEXTENT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_XEXTENT, lMinXExtent, lXExtent, lMaxXExtent - lXPos, 1);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_XEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new valid values for WIA_IPS_XEXTENT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_YEXTENT, lMinYExtent, lYExtent, lMaxYExtent - lYPos, 1);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_YEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new current value for WIA_IPS_XPOS:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_XPOS, lXPos);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_XPOS, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new current value for WIA_IPS_YPOS:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_YPOS, lYPos);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_YPOS, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new current value for WIA_IPS_XEXTENT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_XEXTENT, lXExtent);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_XEXTENT, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Set new current value for WIA_IPS_YEXTENT:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_YEXTENT, lYExtent);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update WIA_IPS_YEXTENT, hr = 0x%08X", hr));
+ }
+ }
+ }
+ }
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Validates new current values for the following dependent WIA properties:
+*
+* WIA_IPS_DOCUMENT_HANDLING_SELECT: either DUPLEX or FRONT_ONLY can be set
+*
+* WIA_IPS_PAGES: the valid range and current value are updated to match
+* the current WIA_IPS_DOCUMENT_HANDLING_SELECT
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise (E_INVALIDARG if
+* an invalid combination is attempted)
+*
+\**************************************************************************/
+
+HRESULT CWiaDriver::ValidateFeedProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext)
+{
+ HRESULT hr = S_OK;
+ BOOL bHandlingSelectChanged = TRUE;
+ LONG lFeederHandlingSelect = FRONT_ONLY;
+ BOOL bPagesChanged = TRUE;
+ LONG lPages = 1;
+ LONG lMaxPages = 0x7FFFFFFF; //maximum value for a signed 32-bit integer
+ LONG lMinPages = 0; //ALL_PAGES
+ LONG lStepPages = 1;
+ WIAS_CHANGED_VALUE_INFO wiasValInfo = {};
+
+ if ((!pWiasContext) || (!pPropertyContext))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid parameters, hr = 0x%08X", hr));
+ }
+
+ //
+ // Check if WIA_IPS_DOCUMENT_HANDLING_SELECT was changed:
+ //
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(wiasGetChangedValueLong(pWiasContext, pPropertyContext, TRUE, WIA_IPS_DOCUMENT_HANDLING_SELECT, &wiasValInfo)))
+ {
+ lFeederHandlingSelect = wiasValInfo.Current.lVal;
+ bHandlingSelectChanged = wiasValInfo.bChanged;
+ }
+ else
+ {
+ bHandlingSelectChanged = FALSE;
+ }
+ }
+
+ //
+ // Check if WIA_IPS_PAGES was changed and read its current value:
+ //
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(wiasGetChangedValueLong(pWiasContext, pPropertyContext, TRUE, WIA_IPS_PAGES, &wiasValInfo)))
+ {
+ lPages = wiasValInfo.Current.lVal;
+ bPagesChanged = wiasValInfo.bChanged;
+ }
+ else
+ {
+ bPagesChanged = FALSE;
+
+ if (bHandlingSelectChanged)
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_PAGES, &lPages, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_PAGES on the Feeder item, hr = 0x%08X", hr));
+ }
+ }
+ }
+ }
+
+ //
+ // If WIA_IPS_DOCUMENT_HANDLING_SELECT is changed verify that only FRONT_ONLY
+ // or DUPLEX is requested to be set, only one at a time:
+ //
+ if (SUCCEEDED(hr) && bHandlingSelectChanged)
+ {
+ if ((DUPLEX != lFeederHandlingSelect) && (FRONT_ONLY != lFeederHandlingSelect))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst,
+ "WIA_IPS_DOCUMENT_HANDLING_SELECT validation failed, only FRONT_ONLY and DUPLEX are valid, only one at a time, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // Read the current WIA_IPS_DOCUMENT_HANDLING_SELECT value if not changed and WIA_IPS_PAGES is changed:
+ //
+ if (SUCCEEDED(hr) && (!bHandlingSelectChanged) && bPagesChanged)
+ {
+ hr = wiasReadPropLong(pWiasContext, WIA_IPS_DOCUMENT_HANDLING_SELECT, &lFeederHandlingSelect, NULL, TRUE);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Error reading current WIA_IPS_DOCUMENT_HANDLING_SELECT on the Feeder item, hr = 0x%08X", hr));
+ }
+ }
+
+ //
+ // If WIA_IPS_DOCUMENT_HANDLING_SELECT is changed and WIA_IPS_PAGES is not, update the valid and,
+ // if needed, current values for WIA_IPS_PAGES. Note that the step WIA_IPS_PAGES value must remain
+ // 1 for duplex in order to allow a legacy WIA 1.0 application to indirectly disable duplex by
+ // settings WIA_DPS_PAGES to 1:
+ //
+ if (SUCCEEDED(hr) && bHandlingSelectChanged && (!bPagesChanged))
+ {
+ if (DUPLEX == lFeederHandlingSelect)
+ {
+ lMaxPages = 0x7FFFFFFE; //maximum even value for a signed 32-bit integer
+ lMinPages = 0; //ALL_PAGES
+ lStepPages = 1; //not 2
+
+ //
+ // Round up the current WIA_IPS_PAGES value to the nearest even number:
+ //
+ if ((lPages > 0) && (lPages % 2))
+ {
+ if (lPages <= (lMaxPages - 1))
+ {
+ lPages += 1;
+ }
+ else if (lPages >= (lMinPages + 2))
+ {
+ lPages -= 1;
+ }
+ else
+ {
+ lPages = 2;
+ }
+ }
+ }
+ else
+ {
+ lMaxPages = 0x7FFFFFFF; //maximum value for a signed 32-bit integer
+ lMinPages = 0; //ALL_PAGES
+ lStepPages = 1;
+ }
+
+ //
+ // Update the range of valid WIA_IPS_PAGES values:
+ //
+ hr = wiasSetValidRangeLong(pWiasContext, WIA_IPS_PAGES, lMinPages, lPages, lMaxPages, lStepPages);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update valid WIA_IPS_PAGES, hr = 0x%08X", hr));
+ }
+
+ //
+ // Update the current WIA_IPS_PAGES value:
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_PAGES, lPages);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update current WIA_IPS_PAGES, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ //
+ // If WIA_IPS_PAGES is changed and WIA_IPS_DOCUMENT_HANDLING_SELECT is not, check if
+ // we need to disable duplex as result of a WIA_IPS_PAGES current value change to 1.
+ // We'll leave duplex enabled if the application changes WIA_IPS_PAGE to another
+ // odd value, the application being responsible in this case to decide itself if
+ // these pages are to be scanned duplex (and the last side discarded) or simplex:
+ //
+ if (SUCCEEDED(hr) && (!bHandlingSelectChanged) && bPagesChanged)
+ {
+ if ((DUPLEX == lFeederHandlingSelect) && (1 == lPages))
+ {
+ lFeederHandlingSelect = FRONT_ONLY;
+
+ hr = wiasWritePropLong(pWiasContext, WIA_IPS_DOCUMENT_HANDLING_SELECT, lFeederHandlingSelect);
+ if (FAILED(hr))
+ {
+ WIAEX_ERROR((g_hInst, "Failed to update current WIA_IPS_DOCUMENT_HANDLING_SELECT, hr = 0x%08X", hr));
+ }
+ }
+ }
+
+ //
+ // If both WIA_IPS_PAGES and WIA_IPS_DOCUMENT_HANDLING_SELECT are changed at the
+ // same time, check if DUPLEX and an odd WIA_IPS_PAGES value are set. We'll allow
+ // odd values other than 1 while DUPLEX is set but not 1:
+ //
+ if (SUCCEEDED(hr) && bHandlingSelectChanged && bPagesChanged)
+ {
+ if ((DUPLEX == lFeederHandlingSelect) && (1 == lPages))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "WIA_IPS_PAGES cannot be set to 1 while setting WIA_IPS_DOCUMENT_HADLING_SELECT to DUPLEX, hr = 0x%08X", hr));
+ }
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Executes additional validation for the imprinter/endorser specific properties.
+* The only imprinter/enorser property that this sample driver needs to validate
+* here is WIA_IPS_PRINTER_ENDORSER_STRING - the characters submitted by the
+* application must match WIA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS. Unsupported
+* WIA_IPS_PRINTER_ENDORSER_VALID_FORMAT_SPECIFIERS are quietly ignored by the
+* driver (pretended to be printed/endorsed as-is).
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nDocumentHandlingSelect - IMPRINTER or ENDORSER (defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateImprinterEndorserProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nDocumentHandlingSelect)
+{
+ HRESULT hr = S_OK;
+ BOOL bStringChanged = TRUE;
+ BSTR bstrNewString = NULL;
+ BSTR bstrOldString = NULL;
+ WIAS_CHANGED_VALUE_INFO wiasValInfo = {};
+
+ if ((!pWiasContext) || (!pPropertyContext) ||
+ ((IMPRINTER != nDocumentHandlingSelect) && (ENDORSER != nDocumentHandlingSelect)))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateImprinterEndorserProperties failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ //
+ // Check if WIA_IPS_PRINTER_ENDORSER_STRING is changed by the application:
+ //
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(wiasGetChangedValueStr(pWiasContext, pPropertyContext, TRUE, WIA_IPS_PRINTER_ENDORSER_STRING, &wiasValInfo)))
+ {
+ //
+ // wiasGetChangedValueStr allocates both Current and Old BSTRs, read them both
+ // even if not using the Old value, we'll need to free both of them when done:
+ //
+ bstrNewString = wiasValInfo.Current.bstrVal;
+ bstrOldString = wiasValInfo.Old.bstrVal;
+ bStringChanged = wiasValInfo.bChanged;
+ }
+ else
+ {
+ bStringChanged = FALSE;
+ }
+ }
+
+ //
+ // If WIA_IPS_PRINTER_ENDORSER_STRING is changed, check if all characters are valid:
+ //
+ if (SUCCEEDED(hr) && bStringChanged && bstrNewString)
+ {
+ PWCHAR szValidChars = (IMPRINTER == nDocumentHandlingSelect) ? SAMPLE_IMPRINTER_VALID_CHARS : SAMPLE_ENDORSER_VALID_CHARS;
+ ULONG ulValidChars = ((IMPRINTER == nDocumentHandlingSelect) ? ARRAYSIZE(SAMPLE_IMPRINTER_VALID_CHARS) : ARRAYSIZE(SAMPLE_ENDORSER_VALID_CHARS)) - 1;
+ ULONG i = 0;
+ BOOL bFound = FALSE;
+
+ while (bstrNewString[i] != NULL)
+ {
+ bFound = FALSE;
+
+ for (ULONG j = 0; j < ulValidChars; j++)
+ {
+ if (bstrNewString[i] == szValidChars[j])
+ {
+ bFound = TRUE;
+ i++;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid character for WIA_IPS_PRINTER_ENDORSER_STRING: 0x%X (%wc), hr = 0x%08X",
+ bstrNewString[i], bstrNewString[i], hr));
+ break;
+ }
+ }
+ }
+
+ //
+ // This sample driver supports only one line of text for its Imprinter/Endorser.
+ // Check that the new WIA_IPS_PRINTER_ENDORSER_STRING value does not contain any
+ // special '$N$'sequences ('new line'). This sample driver will ignore other
+ // formatting sequences that may be contained by the new string:
+ //
+ if (SUCCEEDED(hr) && bStringChanged && bstrNewString)
+ {
+ WCHAR szNewLine[] = L"$N$";
+
+ if (wcsstr(bstrNewString, szNewLine))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid new line ($N$) format sequence for WIA_IPS_PRINTER_ENDORSER_STRING, only one line of text supported, submitted value: %ws, hr = 0x%08X",
+ bstrNewString, hr));
+ }
+ }
+
+ //
+ // Important: both the WIAS_CHANGED_VALUE_INFO::Current.bstrVal and
+ // WIAS_CHANGED_VALUE_INFO::Old.bstrVal BSTRs must be freed.
+ //
+ if (bstrNewString)
+ {
+ SysFreeString(bstrNewString);
+ }
+ if (bstrOldString)
+ {
+ SysFreeString(bstrOldString);
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Validates WIA_IPS_ENABLED_BARCODE_TYPES
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateBarcodeReaderProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext)
+{
+ HRESULT hr = S_OK;
+ BOOL bBarcodeTypesChanged = TRUE;
+
+ if ((!pWiasContext) || (!pPropertyContext))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateImprinterEndorserProperties failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ //
+ // Check if WIA_IPS_ENABLED_BARCODE_TYPES is changed by the application:
+ //
+ if (SUCCEEDED(hr))
+ {
+ //
+ // wiasIsPropChanged fails if the property is not changed, do not fail ValidateBarcodeReaderProperties:
+ //
+ wiasIsPropChanged(WIA_IPS_ENABLED_BARCODE_TYPES, pPropertyContext, &bBarcodeTypesChanged);
+ }
+
+ //
+ // If WIA_IPS_ENABLED_BARCODE_TYPES is changed, read the new (vector) array of values and validate against the valid values:
+ //
+ if (SUCCEEDED(hr) && bBarcodeTypesChanged)
+ {
+ PROPSPEC ps = {};
+ PROPVARIANT pv = {};
+
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = WIA_IPS_ENABLED_BARCODE_TYPES;
+
+ PropVariantInit(&pv);
+
+ hr = wiasReadMultiple(pWiasContext, 1, &ps, &pv, NULL);
+ if (SUCCEEDED(hr))
+ {
+ if ((VT_VECTOR | VT_I4) == pv.vt)
+ {
+ ULONG ulValidValues = ARRAYSIZE(g_lSupportedBarcodeTypes);
+ BOOL bFound = FALSE;
+
+ for (ULONG i = 0; i < pv.cal.cElems; i++)
+ {
+ bFound = FALSE;
+
+ for (ULONG j = 0; j < ulValidValues; j++)
+ {
+ if (g_lSupportedBarcodeTypes[j] == pv.cal.pElems[i])
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Unsupported barcode type: %u, hr = 0x%08X", pv.cal.pElems[i], hr));
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid value type for WIA_IPS_ENABLED_BARCODE_TYPES, expected VT_VECTOR | VT_I4 (%u), got %u, hr = 0x%08X",
+ VT_VECTOR | VT_I4, pv.vt, hr));
+ }
+ }
+ else
+ {
+ WIAEX_ERROR((g_hInst, "wiasReadMultiple(WIA_IPS_ENABLED_BARCODE_TYPES) failed, hr = 0x%08X", hr));
+ }
+
+ PropVariantClear(&pv);
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Validates WIA_IPS_ENABLED_PATCH_CODE_TYPES
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidatePatchCodeReaderProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext)
+{
+ HRESULT hr = S_OK;
+ BOOL bPatchCodeTypesChanged = TRUE;
+
+ if ((!pWiasContext) || (!pPropertyContext))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateImprinterEndorserProperties failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ //
+ // Check if WIA_IPS_ENABLED_PATCH_CODE_TYPES is changed by the application:
+ //
+ if (SUCCEEDED(hr))
+ {
+ //
+ // wiasIsPropChanged fails if the property is not changed, do not fail ValidatePatchCodeReaderProperties:
+ //
+ wiasIsPropChanged(WIA_IPS_ENABLED_PATCH_CODE_TYPES, pPropertyContext, &bPatchCodeTypesChanged);
+ }
+
+ //
+ // If WIA_IPS_ENABLED_PATCH_CODE_TYPES is changed, read the new (vector) array of values and validate against the valid values:
+ //
+ if (SUCCEEDED(hr) && bPatchCodeTypesChanged)
+ {
+ PROPSPEC ps = {};
+ PROPVARIANT pv = {};
+
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = WIA_IPS_ENABLED_PATCH_CODE_TYPES;
+
+ PropVariantInit(&pv);
+
+ hr = wiasReadMultiple(pWiasContext, 1, &ps, &pv, NULL);
+ if (SUCCEEDED(hr))
+ {
+ if ((VT_VECTOR | VT_I4) == pv.vt)
+ {
+ ULONG ulValidValues = ARRAYSIZE(g_lSupportedPatchCodeTypes);
+ BOOL bFound = FALSE;
+
+ for (ULONG i = 0; i < pv.cal.cElems; i++)
+ {
+ bFound = FALSE;
+
+ for (ULONG j = 0; j < ulValidValues; j++)
+ {
+ if (g_lSupportedPatchCodeTypes[j] == pv.cal.pElems[i])
+ {
+ bFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Unsupported patch code type: %u, hr = 0x%08X", pv.cal.pElems[i], hr));
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid value type for WIA_IPS_ENABLED_PATCH_CODE_TYPES, expected VT_VECTOR | VT_I4 (%u), got %u, hr = 0x%08X",
+ VT_VECTOR | VT_I4, pv.vt, hr));
+ }
+ }
+ else
+ {
+ WIAEX_ERROR((g_hInst, "wiasReadMultiple(WIA_IPS_ENABLED_PATCH_CODE_TYPES) failed, hr = 0x%08X", hr));
+ }
+
+ PropVariantClear(&pv);
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateMicrReaderProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext)
+{
+ HRESULT hr = S_OK;
+
+ if ((!pWiasContext) || (!pPropertyContext))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateMicrReaderProperties failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ //
+ // Nothing special to validate here
+ //
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for CWiaDriver::ValidateColorDropProperties.
+*
+* Validates a RGB color drop property WIA_IPS_COLOR_DROP_RED, WIA_IPS_COLOR_DROP_GREEN and
+* WIA_IPS_COLOR_DROP_BLUE
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nChannel - WIA_COLOR_DROP_RED, WIA_COLOR_DROP_GREEN or
+* WIA_COLOR_DROP_BLUE (as defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateColorDropProperty(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nChannel)
+{
+ HRESULT hr = S_OK;
+ BOOL bChanged = TRUE;
+ UINT nProp = 0;
+
+ if ((!pWiasContext) || (!pPropertyContext) ||
+ ((WIA_COLOR_DROP_RED != nChannel) && (WIA_COLOR_DROP_GREEN != nChannel) && (WIA_COLOR_DROP_BLUE != nChannel)))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateColorDropProperty failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ switch (nChannel)
+ {
+ case WIA_COLOR_DROP_RED:
+ nProp = WIA_IPS_COLOR_DROP_RED;
+ break;
+
+ case WIA_COLOR_DROP_GREEN:
+ nProp = WIA_IPS_COLOR_DROP_GREEN;
+ break;
+
+ case WIA_COLOR_DROP_BLUE:
+ nProp = WIA_IPS_COLOR_DROP_BLUE;
+ }
+
+ //
+ // Check if this WIA_IPS_COLOR_DROP_* property is changed by the application:
+ //
+ if (SUCCEEDED(hr))
+ {
+ //
+ // wiasIsPropChanged fails if the property is not changed, do not fail validation because of this:
+ //
+ wiasIsPropChanged(nProp, pPropertyContext, &bChanged);
+ }
+
+ //
+ // If this WIA_IPS_COLOR_DROP_* property is changed, read the new (vector) array of values and validate
+ // both against WIA_IPS_COLOR_DROP_MULTI and the valid range of values (from 0 and 100, inclusive):
+ //
+ if (SUCCEEDED(hr) && bChanged)
+ {
+ PROPSPEC ps = {};
+ PROPVARIANT pv = {};
+
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = nProp;
+
+ PropVariantInit(&pv);
+
+ hr = wiasReadMultiple(pWiasContext, 1, &ps, &pv, NULL);
+ if (SUCCEEDED(hr))
+ {
+ if ((VT_VECTOR | VT_I4) == pv.vt)
+ {
+ if (pv.cal.cElems > g_lMaxDropColors)
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Unsupported number of drop out entries for property %u: %u, supported up to: %u, hr = 0x%08X",
+ nProp, pv.cal.cElems, g_lMaxDropColors, hr));
+ }
+ else
+ {
+ for (ULONG i = 0; i < pv.cal.cElems; i++)
+ {
+ if ((pv.cal.pElems[i] < 0) || (pv.cal.pElems[i] > 100))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst,
+ "Unsupported color drop value for property %u at vector position %u: %u, valid range is from 0 to 100 inclusive, hr = 0x%08X",
+ nProp, i, pv.cal.pElems[i], hr));
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "Invalid value type for property %u, expected VT_VECTOR | VT_I4 (%u), got %u, hr = 0x%08X",
+ nProp, VT_VECTOR | VT_I4, pv.vt, hr));
+ }
+ }
+ else
+ {
+ WIAEX_ERROR((g_hInst, "wiasReadMultiple(property %u) failed, hr = 0x%08X", nProp, hr));
+ }
+
+ PropVariantClear(&pv);
+ }
+
+ return hr;
+}
+
+/**************************************************************************\
+*
+* Helper for IWiaMinIDrv::drvValidateItemProperties.
+*
+* Validates WIA_IPS_COLOR_DROP_RED, WIA_IPS_COLOR_DROP_GREEN and
+* WIA_IPS_COLOR_DROP_BLUE
+*
+* Parameters:
+*
+* pWiasContext - pointer to the item context
+* pPropertyContext - pointer to the property context which
+* indicates which properties are being written
+* nDocumentHandlingSelect - FLAT or FEED (as defined in wiadef.h)
+*
+* Return Value:
+*
+* S_OK if successful, an error HRESULT otherwise
+*
+\**************************************************************************/
+HRESULT CWiaDriver::ValidateColorDropProperties(
+ _In_ BYTE* pWiasContext,
+ _In_ WIA_PROPERTY_CONTEXT* pPropertyContext,
+ UINT nDocumentHandlingSelect)
+{
+ HRESULT hr = S_OK;
+
+ if ((!pWiasContext) || (!pPropertyContext) ||
+ ((FLAT != nDocumentHandlingSelect) && (FEED != nDocumentHandlingSelect)))
+ {
+ hr = E_INVALIDARG;
+ WIAEX_ERROR((g_hInst, "CWiaDriver::ValidateColorDropProperties failed, invalid parameter, hr = 0x%08X", hr));
+ }
+
+ //
+ // Validate WIA_IPS_COLOR_DROP_RED (error logging is covered by ValidateColorDropProperty):
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = ValidateColorDropProperty(pWiasContext, pPropertyContext, WIA_COLOR_DROP_RED);
+ }
+
+ //
+ // Validate WIA_IPS_COLOR_DROP_GREEN (error logging is covered by ValidateColorDropProperty):
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = ValidateColorDropProperty(pWiasContext, pPropertyContext, WIA_COLOR_DROP_GREEN);
+ }
+
+ //
+ // Validate WIA_IPS_COLOR_DROP_BLUE (error logging is covered by ValidateColorDropProperty):
+ //
+ if (SUCCEEDED(hr))
+ {
+ hr = ValidateColorDropProperty(pWiasContext, pPropertyContext, WIA_COLOR_DROP_BLUE);
+ }
+
+ return hr;
+}