diff options
Diffstat (limited to 'wia/ProdScan/InitProp.cpp')
| -rw-r--r-- | wia/ProdScan/InitProp.cpp | 3134 |
1 files changed, 3134 insertions, 0 deletions
diff --git a/wia/ProdScan/InitProp.cpp b/wia/ProdScan/InitProp.cpp new file mode 100644 index 00000000..0254112d --- /dev/null +++ b/wia/ProdScan/InitProp.cpp @@ -0,0 +1,3134 @@ +/************************************************************************** +* +* Copyright � Microsoft Corporation +* +* File Name: InitProp.cpp +* +* Description: This file contains code for WIA property initialization +* for the Production Scanner Driver Sample +* +***************************************************************************/ + +#include "stdafx.h" + +/**************************************************************************\ +* +* Initializes the Root item properties +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeRootItemProperties( + _In_ BYTE* pWiasContext) +{ + HRESULT hr = S_OK; + + WIAEX_TRACE_BEGIN; + + // + // Validate input: + // + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + // + // Initialize Root item properties: + // + if (SUCCEEDED(hr)) + { + CWIAPropertyManager PropertyManager; + + // + // WIA_IPA_ITEM_CATEGORY: + // + GUID guidItemCategory = WIA_CATEGORY_ROOT; + hr = PropertyManager.AddProperty(WIA_IPA_ITEM_CATEGORY, WIA_IPA_ITEM_CATEGORY_STR, RN, guidItemCategory); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ITEM_CATEGORY, hr = 0x%08X", hr)); + } + + // + // WIA_IPA_ACCESS_RIGHTS + // + if (SUCCEEDED(hr)) + { + LONG lAccessRights = WIA_ITEM_READ; + + hr = PropertyManager.AddProperty(WIA_IPA_ACCESS_RIGHTS, WIA_IPA_ACCESS_RIGHTS_STR, RF, lAccessRights, lAccessRights); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ACCESS_RIGHTS, hr = 0x%08X", hr)); + } + } + + // + // WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES and default WIA_DPS_DOCUMENT_HANDLING_STATUS: + // + + LONG lDocumentHandlingCapabilities = AUTO_SOURCE | FLAT | FEED | DUP | IMPRINTER | ENDORSER | + BARCODE_READER | PATCH_CODE_READER | MICR_READER; + + LONG lDocumentHandlingStatus = FLAT_READY | FEED_READY | DUP_READY | IMPRINTER_READY | ENDORSER_READY | + BARCODE_READER_READY | PATCH_CODE_READER_READY | MICR_READER_READY; + + LONG lValidDocumentHandlingStatus = FLAT_COVER_UP | FLAT_READY | FEED_READY | DUP_READY | IMPRINTER_READY | + ENDORSER_READY | BARCODE_READER_READY | PATCH_CODE_READER_READY | MICR_READER_READY | + PAPER_JAM | PATH_COVER_UP | MULTIPLE_FEED | DEVICE_ATTENTION | LAMP_ERR; + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES, + WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES_STR , RN, lDocumentHandlingCapabilities); + + if(FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES, hr = 0x%08X", hr)); + } + } + + // + // WIA_DPS_DOCUMENT_HANDLING_STATUS: + // + if (SUCCEEDED(hr)) + { + // + // Initialize with default ready flag values: + // + hr = PropertyManager.AddProperty(WIA_DPS_DOCUMENT_HANDLING_STATUS, + WIA_DPS_DOCUMENT_HANDLING_STATUS_STR, RN, lDocumentHandlingStatus, lValidDocumentHandlingStatus); + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_DPS_DOCUMENT_HANDLING_STATUS, hr = 0x%08X", hr)); + } + } + + // + // WIA_DPA_CONNECT_STATUS + // + // The sample device is always available: + // + if (SUCCEEDED(hr)) + { + LONG lDeviceConnected = 1; + hr = PropertyManager.AddProperty(WIA_DPA_CONNECT_STATUS, WIA_DPA_CONNECT_STATUS_STR, RN, lDeviceConnected); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_DPA_CONNECT_STATUS, hr = 0x%08X", hr)); + } + } + + // + // WIA_DPS_SCAN_AVAILABLE_ITEM: + // + if (SUCCEEDED(hr)) + { + // + // If the global (per driver instance) m_bstrScanAvailableItem is not yet initialized + // initialize it now to an empty string. Note that because we use here m_bstrScanAvailableItem + // to initialize the property we do not need to execute UpdateScanAvailableItemProperty: + // + if (!m_bstrScanAvailableItem) + { + hr = UpdateScanAvailableItemName(NULL); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize the scan available item name, hr = 0x%08X", hr)); + } + } + else + { + WIAS_TRACE((g_hInst, "Scan available from %ws", m_bstrScanAvailableItem)); + } + + if (SUCCEEDED(hr)) + { + #pragma prefast(suppress:__WARNING_INVALID_PARAM_VALUE_1, "m_bstrScanAvailableItem is allocated to an empty string by the UpdateScanAvailableItemName call above" + hr = PropertyManager.AddProperty(WIA_DPS_SCAN_AVAILABLE_ITEM, WIA_DPS_SCAN_AVAILABLE_ITEM_STR, RN, m_bstrScanAvailableItem); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_DPS_SCAN_AVAILABLE_ITEM, hr = 0x%08X", hr)); + } + } + } + + // + // Set the properties: + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA root item properties, hr = 0x%08X", hr)); + } + } + else + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ITEM_CATEGORY, hr = 0x%08X", hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Wrapper method to initializes the properties for the child items this +* sample driver creates. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* nDocumentHandlingSelect - a WIA_DPS_DOCUMENT_HANDLING_SELECT value (such +* as FLAT or FEED (defined in wiadef.h) identifying +* the item being initialized +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeChildItemProperties( + _In_ BYTE* pWiasContext, + UINT nDocumentHandlingSelect) + +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + WIAEX_TRACE_BEGIN; + + // + // No need to validate parameters of trace failures here, the called functions + // do the validation and output full error traces: + // + hr = InitializeCommonChildProperties(pWiasContext, nDocumentHandlingSelect); + if (SUCCEEDED(hr)) + { + if ((FLAT == nDocumentHandlingSelect) || (FEEDER == nDocumentHandlingSelect)) + { + hr = InitializeFlatbedFeederProperties(pWiasContext, nDocumentHandlingSelect); + if (SUCCEEDED(hr) && (FEEDER == nDocumentHandlingSelect)) + { + hr = InitializeFeederSpecificProperties(pWiasContext); + } + } + else if ((IMPRINTER == nDocumentHandlingSelect) || (ENDORSER == nDocumentHandlingSelect)) + { + hr = InitializeImprinterEndorserProperties(pWiasContext, nDocumentHandlingSelect); + } + else if (BARCODE_READER == nDocumentHandlingSelect) + { + hr = InitializeBarcodeReaderProperties(pWiasContext); + } + else if (PATCH_CODE_READER == nDocumentHandlingSelect) + { + hr = InitializePatchCodeReaderProperties(pWiasContext); + } + else if (MICR_READER == nDocumentHandlingSelect) + { + hr = InitializeMicrReaderProperties(pWiasContext); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes common child item properties (properties common to all +* data source items this driver creates: Flatbed, Feeder, Auto, Imprinter, etc. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* nDocumentHandlingSelect - a WIA_DPS_DOCUMENT_HANDLING_SELECT value (such +* as FLAT or FEED (defined in wiadef.h) identifying +* the item being initialized +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeCommonChildProperties( + _In_ BYTE* pWiasContext, + UINT nDocumentHandlingSelect) + +{ + HRESULT hr = S_OK; + + CWIAPropertyManager PropertyManager; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeCommonChildProperties, invalid item context parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPA_ITEM_CATEGORY + // + if (SUCCEEDED(hr)) + { + GUID guidItemCategory = WIA_CATEGORY_FLATBED; + + switch (nDocumentHandlingSelect) + { + case FLAT: + guidItemCategory = WIA_CATEGORY_FLATBED; + break; + + case FEED: + guidItemCategory = WIA_CATEGORY_FEEDER; + break; + + case AUTO_SOURCE: + guidItemCategory = WIA_CATEGORY_AUTO; + break; + + case IMPRINTER: + guidItemCategory = WIA_CATEGORY_IMPRINTER; + break; + + case ENDORSER: + guidItemCategory = WIA_CATEGORY_ENDORSER; + break; + + case BARCODE_READER: + guidItemCategory = WIA_CATEGORY_BARCODE_READER; + break; + + case PATCH_CODE_READER: + guidItemCategory = WIA_CATEGORY_PATCH_CODE_READER; + break; + + case MICR_READER: + guidItemCategory = WIA_CATEGORY_MICR_READER; + break; + + default: + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeCommonChildProperties, invalid item (%u) parameter, hr = 0x%08X", + nDocumentHandlingSelect, hr)); + } + + hr = PropertyManager.AddProperty(WIA_IPA_ITEM_CATEGORY, WIA_IPA_ITEM_CATEGORY_STR, RN, guidItemCategory); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ITEM_CATEGORY for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_ACCESS_RIGHTS + // + if (SUCCEEDED(hr)) + { + LONG lAccessRights = WIA_ITEM_READ; + + hr = PropertyManager.AddProperty(WIA_IPA_ACCESS_RIGHTS, WIA_IPA_ACCESS_RIGHTS_STR, RF, lAccessRights, lAccessRights); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ACCESS_RIGHTS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_FORMAT + // + // For image transfers, this sample driver supports the DIB (mandatory default), EXIF and Raw image file formats. + // + // The sample imprinter and endorser items support the CSV (mandatory default) and TXT for text transfers and + // DIB (mandatory default) for graphics transfers. Default data transfer mode is text (required). + // + // The sample barcode, patch code and MICR reader items support the required XML and Raw metadata transfers. + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<GUID> guidFormatArray; + + if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect) || + (AUTO_SOURCE == nDocumentHandlingSelect)) + { + guidFormatArray.Append(WiaImgFmt_BMP); + guidFormatArray.Append(WiaImgFmt_EXIF); + guidFormatArray.Append(WiaImgFmt_RAW); + } + else if ((IMPRINTER == nDocumentHandlingSelect) || (ENDORSER == nDocumentHandlingSelect)) + { + guidFormatArray.Append(WiaImgFmt_CSV); + guidFormatArray.Append(WiaImgFmt_TXT); + guidFormatArray.Append(WiaImgFmt_BMP); + } + else if (BARCODE_READER == nDocumentHandlingSelect) + { + guidFormatArray.Append(WiaImgFmt_XMLBAR); + guidFormatArray.Append(WiaImgFmt_RAWBAR); + } + else if (PATCH_CODE_READER == nDocumentHandlingSelect) + { + guidFormatArray.Append(WiaImgFmt_XMLPAT); + guidFormatArray.Append(WiaImgFmt_RAWPAT); + } + else if (MICR_READER == nDocumentHandlingSelect) + { + guidFormatArray.Append(WiaImgFmt_XMLMIC); + guidFormatArray.Append(WiaImgFmt_RAWMIC); + } + + hr = PropertyManager.AddProperty(WIA_IPA_FORMAT, WIA_IPA_FORMAT_STR, RWL, guidFormatArray[0], guidFormatArray[0], &guidFormatArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_FORMAT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_TYMED + // + // This sample driver supports only TYMED_FILE (single page files) for image as well as text and metadata data transfers + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lTymedArray; + lTymedArray.Append(TYMED_FILE); + + hr = PropertyManager.AddProperty(WIA_IPA_TYMED, WIA_IPA_TYMED_STR, RWL, lTymedArray[0], lTymedArray[0], &lTymedArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_TYMED for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_PREFERRED_FORMAT + // + // For image transfers, this sample driver reports EXIF as the preferred transfer file format. + // + // For printer/endorser transfers, this driver reports CSV as the preferred transfer file format. + // + // For barcode, patch code and MICR metadata transfers, this driver reports XML as the preferred transfer file format. + // + if (SUCCEEDED(hr)) + { + GUID guidPreferredFormat = {}; + + if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect) || + (AUTO_SOURCE == nDocumentHandlingSelect)) + { + guidPreferredFormat = WiaImgFmt_EXIF; + } + else if ((IMPRINTER == nDocumentHandlingSelect) || (ENDORSER == nDocumentHandlingSelect)) + { + guidPreferredFormat = WiaImgFmt_CSV; + } + else if (BARCODE_READER == nDocumentHandlingSelect) + { + guidPreferredFormat = WiaImgFmt_XMLBAR; + } + else if (PATCH_CODE_READER == nDocumentHandlingSelect) + { + guidPreferredFormat = WiaImgFmt_XMLPAT; + } + else if (MICR_READER == nDocumentHandlingSelect) + { + guidPreferredFormat = WiaImgFmt_XMLMIC; + } + + hr = PropertyManager.AddProperty(WIA_IPA_PREFERRED_FORMAT, WIA_IPA_PREFERRED_FORMAT_STR, RN, guidPreferredFormat); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_PREFERRED_FORMAT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_FILENAME_EXTENSION + // + if (SUCCEEDED(hr)) + { + BSTR bstrFileExtension = NULL; + + // + // Note that WIA_IPA_FILENAME_EXTENSION must match the WIA_IPA_FORMAT current value, not WIA_IPA_PREFERRED_FORMAT: + // + if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect) || + (AUTO_SOURCE == nDocumentHandlingSelect)) + { + bstrFileExtension = SysAllocString(FILE_EXT_BMP); + } + else if ((IMPRINTER == nDocumentHandlingSelect) || (ENDORSER == nDocumentHandlingSelect)) + { + bstrFileExtension = SysAllocString(FILE_EXT_CSV); + } + else if ((BARCODE_READER == nDocumentHandlingSelect) || (PATCH_CODE_READER == nDocumentHandlingSelect) || + (MICR_READER == nDocumentHandlingSelect)) + { + bstrFileExtension = SysAllocString(FILE_EXT_XML); + } + + if (bstrFileExtension) + { + hr = PropertyManager.AddProperty(WIA_IPA_FILENAME_EXTENSION, WIA_IPA_FILENAME_EXTENSION_STR, RN, bstrFileExtension); + + SysFreeString(bstrFileExtension); + bstrFileExtension = NULL; + } + else + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Could not allocate the file name extension property value, hr = 0x%08X", hr)); + } + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_FILENAME_EXTENSION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_COMPRESSION + // + // For image transfers, this sample driver supports no compression (mandatory default, for DIB and Raw transfers) + // and JPEG (EEXIF transfers). The sample driver also pretends to support auto-compression (WIA_COMPRESSION_AUTO) + // but in auto-compression mode JPEG compression is always selected. + // + // For all other metadata transfers, this sample driver supports no compression (mandatory default). + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lCompressionArray; + + lCompressionArray.Append(WIA_COMPRESSION_NONE); + if ((FLAT == nDocumentHandlingSelect) || (FEED == nDocumentHandlingSelect) || (AUTO_SOURCE == nDocumentHandlingSelect)) + { + lCompressionArray.Append(WIA_COMPRESSION_JPEG); + lCompressionArray.Append(WIA_COMPRESSION_AUTO); + } + + hr = PropertyManager.AddProperty(WIA_IPA_COMPRESSION, WIA_IPA_COMPRESSION_STR, RWL, lCompressionArray[0], lCompressionArray[0], &lCompressionArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_COMPRESSION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties common to the Flatbed and Feeder items. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* nDocumentHandlingSelect - FLAT or FEED (defined in wiadef.h) +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeFlatbedFeederProperties( + _In_ BYTE* pWiasContext, + UINT nDocumentHandlingSelect) + +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if ((!pWiasContext) || ((FLAT != nDocumentHandlingSelect) && (FEED != nDocumentHandlingSelect))) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeFlatbedFeederProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPA_ITEM_SIZE + // + if (SUCCEEDED(hr)) + { + LONG lItemSize = 0; + + hr = PropertyManager.AddProperty(WIA_IPA_ITEM_SIZE, WIA_IPA_ITEM_SIZE_STR, RN, lItemSize); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_ITEM_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_PLANAR: + // + LONG lPlanar = WIA_PACKED_PIXEL; + + hr = PropertyManager.AddProperty(WIA_IPA_PLANAR, WIA_IPA_PLANAR_STR, RN, lPlanar); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_PLANAR for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + // + // WIA_IPA_DATATYPE + // + // This sample driver supports 24-bpp RGB color and 8-bpp Grayscale for the image transfers, as well as the auto color mode. + // When WIA_DATA_AUTO is set the sample driver choses randomly between WIA_DATA_GRAYSCALE and WIA_DATA_COLOR. + // A real driver should base this decision on the actual document that is scanned: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lDataTypeArray; + lDataTypeArray.Append(WIA_DATA_GRAYSCALE); + lDataTypeArray.Append(WIA_DATA_COLOR); + lDataTypeArray.Append(WIA_DATA_AUTO); + + hr = PropertyManager.AddProperty(WIA_IPA_DATATYPE, WIA_IPA_DATATYPE_STR, RWL, lDataTypeArray[0], lDataTypeArray[0], &lDataTypeArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_DATATYPE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_DEPTH + // + // This sample driver supports 24-bpp RGB color and 8-bpp Grayscale, as well as the auto value (WIA_DEPTH_AUTO or 0): + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lDepthArray; + lDepthArray.Append(8); + lDepthArray.Append(24); + lDepthArray.Append(WIA_DEPTH_AUTO); + + hr = PropertyManager.AddProperty(WIA_IPA_DEPTH , WIA_IPA_DEPTH_STR, RWLC, lDepthArray[0], lDepthArray[0], &lDepthArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_DEPTH for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_CHANNELS_PER_PIXEL + // + // This sample driver supports 1 and 3 channels (samples) per pixel + // + if (SUCCEEDED(hr)) + { + LONG lChannelsPerPixel = 1; //default value that matches the default WIA_DATA_GRAYSCALE + + hr = PropertyManager.AddProperty(WIA_IPA_CHANNELS_PER_PIXEL, WIA_IPA_CHANNELS_PER_PIXEL_STR, RN, lChannelsPerPixel); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_CHANNELS_PER_PIXEL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_BITS_PER_CHANNEL + // + // This sample driver supports only 8 bits per channel (sample) + // + if (SUCCEEDED(hr)) + { + LONG lBitsPerChannel = 8; + + hr = PropertyManager.AddProperty(WIA_IPA_BITS_PER_CHANNEL, WIA_IPA_BITS_PER_CHANNEL_STR, RN, lBitsPerChannel); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_BITS_PER_CHANNEL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_RAW_BITS_PER_CHANNEL + // + if (SUCCEEDED(hr)) + { + BYTE bRawBitsPerChannel[] = { 8 }; //to match the default WIA_DATA_GRAYSCALE + + hr = PropertyManager.AddProperty(WIA_IPA_RAW_BITS_PER_CHANNEL, WIA_IPA_RAW_BITS_PER_CHANNEL_STR, RN, &bRawBitsPerChannel[0], 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_RAW_BITS_PER_CHANNEL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + + // + // WIA_IPS_CUR_INTENT + // + if (SUCCEEDED(hr)) + { + LONG lCurrentIntent = WIA_INTENT_NONE; + LONG lValidIntents = WIA_INTENT_IMAGE_TYPE_COLOR | WIA_INTENT_IMAGE_TYPE_GRAYSCALE | WIA_INTENT_MAXIMIZE_QUALITY | WIA_INTENT_MINIMIZE_SIZE; + + hr = PropertyManager.AddProperty(WIA_IPS_CUR_INTENT, WIA_IPS_CUR_INTENT_STR, RWF, lCurrentIntent, lValidIntents); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_CUR_INTENT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_OPTICAL_XRES and WIA_IPS_OPTICAL_YRES + // + // This sample driver reports OPTICAL_RESOLUTION DPI as optical resolution on both scan directions + // + if (SUCCEEDED(hr)) + { + LONG lOpticalResolution = OPTICAL_RESOLUTION; + + hr = PropertyManager.AddProperty(WIA_IPS_OPTICAL_XRES, WIA_IPS_OPTICAL_XRES_STR, RN, lOpticalResolution); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OPTICAL_XRES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_OPTICAL_YRES, WIA_IPS_OPTICAL_YRES_STR, RN, lOpticalResolution); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OPTICAL_YRES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_XRES and WIA_IPS_YRES + // + // This sample driver supports OPTICAL_RESOLUTION DPI as the only scan resolution for both scan directions + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lResolutionArray; + lResolutionArray.Append(OPTICAL_RESOLUTION); + + // + // Add WIA_IPS_XRES and WIA_IPS_YRES as WIA_PROP_LIST: + // + hr = PropertyManager.AddProperty(WIA_IPS_XRES, WIA_IPS_XRES_STR, RWLC, lResolutionArray[0], lResolutionArray[0], &lResolutionArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_XRES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_YRES, WIA_IPS_YRES_STR, RWLC, lResolutionArray[0], lResolutionArray[0], &lResolutionArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_YRES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_XSCALING and WIA_IPS_YSCALING + // + // This sample driover supports only 100% scaling (which means no actual scaling) + // + if (SUCCEEDED(hr)) + { + LONG lScaling = 100; + + hr = PropertyManager.AddProperty(WIA_IPS_XSCALING, WIA_IPS_XSCALING_STR, RWRC, lScaling, lScaling, lScaling, lScaling, 0); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_XSCALING for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_YSCALING, WIA_IPS_YSCALING_STR, RWRC, lScaling, lScaling, lScaling, lScaling, 0); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_YSCALING for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_MIN_HORIZONTAL_SIZE, WIA_IPS_MAX_HORIZONTAL_SIZE, WIA_IPS_MIN_VERTICAL_SIZE and WIA_IPS_MAX_VERTICAL_SIZE + // + // This sample driver supports for both flatbed and feeder the following: + // + // Minimum scan region is MIN_SCAN_AREA_WIDTH x MIN_SCAN_AREA_HEIGHT + // Maximum scan region is MAX_SCAN_AREA_WIDTH x MAX_SCAN_AREA_HEIGHT + // + if (SUCCEEDED(hr)) + { + LONG lMaximumWidth = MAX_SCAN_AREA_WIDTH; + + hr = PropertyManager.AddProperty(WIA_IPS_MAX_HORIZONTAL_SIZE, WIA_IPS_MAX_HORIZONTAL_SIZE_STR, RN, lMaximumWidth); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MAX_HORIZONTAL_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + LONG lMaximumHeight = MAX_SCAN_AREA_HEIGHT; + + hr = PropertyManager.AddProperty(WIA_IPS_MAX_VERTICAL_SIZE, WIA_IPS_MAX_VERTICAL_SIZE_STR, RN, lMaximumHeight); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MAX_VERTICAL_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + LONG lMinimumWidth = MIN_SCAN_AREA_WIDTH; + + hr = PropertyManager.AddProperty(WIA_IPS_MIN_HORIZONTAL_SIZE, WIA_IPS_MIN_HORIZONTAL_SIZE_STR, RN, lMinimumWidth); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MIN_HORIZONTAL_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + LONG lMinimumHeight = MIN_SCAN_AREA_HEIGHT; + + hr = PropertyManager.AddProperty(WIA_IPS_MIN_VERTICAL_SIZE, WIA_IPS_MIN_VERTICAL_SIZE_STR, RN, lMinimumHeight); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MIN_VERTICAL_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_XPOS, WIA_IPS_YPOS, WIA_IPS_XEXTENT and WIA_IPS_YEXTENT + // + // In general, for the flatbed item, valid values are to be initialized from + // (considering current WIA_IPS_X/YRES and WIA_IPS_X/YSCALING): + // + // WIA_IPS_MIN_HORIZONTAL_SIZE, + // WIA_IPS_MIN_VERTICAL_SIZE, + // WIA_IPS_MAX_HORIZONTAL_SIZE, + // WIA_IPS_MAX_VERTICAL_SIZE + // + // For the feeder item valid values are to be initialized from + // the size of the currently selected document size, considering + // orientation and current WIA_IPS_X/YRES/SCALING: + // + // WIA_IPS_PAGE_SIZE + // WIA_IPS_PAGE_WIDTH/HEIGHT (if WIA_IPS_PAGE_SIZE is set to CUSTOM, default) + // WIA_IPS_ORIENTATION + // + // The default scan region should cover the entire available scan area. + // + + LONG lMinXExtent = 1; + LONG lMinYExtent = 1; + LONG lMaxXExtent = 2; + LONG lMaxYExtent = 2; + + LONG lXResolution = OPTICAL_RESOLUTION; + LONG lYResolution = OPTICAL_RESOLUTION; + + if (SUCCEEDED(hr) && (AUTO_SOURCE != nDocumentHandlingSelect)) + { + // + // Convert back from 1/1000" values x pixels-per-inch: + // + lMinXExtent = (MIN_SCAN_AREA_WIDTH * lXResolution) / 1000; + if (!lMinXExtent) + { + lMinXExtent = 1; + } + lMinYExtent = (MIN_SCAN_AREA_HEIGHT * lYResolution) / 1000; + if (!lMinYExtent) + { + lMinYExtent = 1; + } + lMaxXExtent = (MAX_SCAN_AREA_WIDTH * lXResolution) / 1000; + lMaxYExtent = (MAX_SCAN_AREA_HEIGHT * lYResolution) / 1000; + + // + // IMPORTANT: do not round up! + // + // lMaxXExtent = (LONG)((((float)MAX_SCAN_AREA_WIDTH * (float)lXResolution) / 1000.0f) + 0.5f); + // lMaxYExtent = (LONG)((((float)MAX_SCAN_AREA_HEIGHT * (float)lYResolution) / 1000.0f) + 0.5f); + // + + if ((lMaxXExtent < 1) || (lMaxYExtent < 1) || (lMinXExtent > lMaxXExtent) || (lMinYExtent > lMaxYExtent)) + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Invalid resolution and-or minimum and-or maximum scan area size values, hr = 0x%08X", hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_XPOS, WIA_IPS_XPOS_STR, RWRC, 0, 0, 0, lMaxXExtent - lMinXExtent, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_XPOS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_YPOS, WIA_IPS_YPOS_STR, RWRC, 0, 0, 0, lMaxYExtent - lMinYExtent, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_YPOS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_XEXTENT, WIA_IPS_XEXTENT_STR, RWRC, lMaxXExtent, lMaxXExtent, lMinXExtent, lMaxXExtent, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_XEXTENT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_YEXTENT, WIA_IPS_YEXTENT_STR, RWRC, lMaxYExtent, lMaxYExtent, lMinYExtent, lMaxYExtent, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_YEXTENT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_BRIGHTNESS and WIA_IPS_CONTRAST + // + // This sample driver simulates brightness and contrast adjustment between + // a standard range from -1000 to 1000, with a default value of 0. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_BRIGHTNESS, WIA_IPS_BRIGHTNESS_STR, RWRC, 0, 0, -1000, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BRIGHTNESS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_CONTRAST, WIA_IPS_CONTRAST_STR, RWRC, 0, 0, -1000, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_CONTRAST for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_ROTATION + // + // This sample driver supports only 0 degrees rotation (no actual rotation) + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lRotationArray; + lRotationArray.Append(0); + + hr = PropertyManager.AddProperty(WIA_IPS_ROTATION, WIA_IPS_ROTATION_STR, RWLC, lRotationArray[0], lRotationArray[0], &lRotationArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ROTATION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_THRESHOLD + // + // This sample driver supports only the default value of 128 + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_THRESHOLD, WIA_IPS_THRESHOLD_STR, RWRC, 128, 128, 128, 128, 0); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_THRESHOLD for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PREVIEW + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lScanModeArray; + lScanModeArray.Append(WIA_FINAL_SCAN); + lScanModeArray.Append(WIA_PREVIEW_SCAN); + + hr = PropertyManager.AddProperty(WIA_IPS_PREVIEW, WIA_IPS_PREVIEW_STR, RWL, lScanModeArray[0], lScanModeArray[0], &lScanModeArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PREVIEW for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_SHOW_PREVIEW_CONTROL + // + if (SUCCEEDED(hr)) + { + // + // There is the option to disable the preview control for Feeder but this sample driver is not using it: + // + // lShowPreviewControl = (FLAT == nDocumentHandlingSelect) ? WIA_SHOW_PREVIEW_CONTROL : WIA_DONT_SHOW_PREVIEW_CONTROL; + // + + LONG lShowPreviewControl = WIA_SHOW_PREVIEW_CONTROL; + + hr = PropertyManager.AddProperty(WIA_IPS_SHOW_PREVIEW_CONTROL, WIA_IPS_SHOW_PREVIEW_CONTROL_STR, RN, lShowPreviewControl); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SHOW_PREVIEW_CONTROL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION + // + if (SUCCEEDED(hr)) + { + BOOL lSupportsChildItem = FALSE; + + hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION_STR, RN, lSupportsChildItem); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PHOTOMETRIC_INTERP + // + // This sample driver supports only the default value of WIA_PHOTO_WHITE_1 + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lPhotoInterpArray; + lPhotoInterpArray.Append(WIA_PHOTO_WHITE_1); + + hr = PropertyManager.AddProperty(WIA_IPS_PHOTOMETRIC_INTERP, WIA_IPS_PHOTOMETRIC_INTERP_STR, RWL, lPhotoInterpArray[0], lPhotoInterpArray[0], &lPhotoInterpArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PHOTOMETRIC_INTERP for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // Even though deprecated the following "image information" properties are still required + // for compatibility with existing legacy XP applications, including Scanner and Camera Wizard, + // applications using the default WIA UI (including Paint) and the TWAIN applications using + // the WIA driver though the TWAIN - WIA compatibility layer: + // + // 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 + // + // All these values must match the exact dimensions of the final image to be transferred + // to the application, a mismatch could cause unpredictable behaviour, including Divide by Zero + // and Access Violation errors in the application attempting to receive data that doesn't exist. + // + + if (SUCCEEDED(hr)) + { + LONG lPixelsPerLine = lMaxXExtent; + + hr = PropertyManager.AddProperty(WIA_IPA_PIXELS_PER_LINE, WIA_IPA_PIXELS_PER_LINE_STR, RN, lPixelsPerLine); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_PIXELS_PER_LINE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + LONG lNumberOfLines = lMaxYExtent; + + hr = PropertyManager.AddProperty(WIA_IPA_NUMBER_OF_LINES, WIA_IPA_NUMBER_OF_LINES_STR, RN, lNumberOfLines); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_NUMBER_OF_LINES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + // + // DIB (the default image file transfer format) lines must be DWORD aligned, meaning + // that each line must be multiple by 4 bytes in length, padded if necessary at the end: + // + LONG lBytesPerLine = 2552; + + hr = PropertyManager.AddProperty(WIA_IPA_BYTES_PER_LINE, WIA_IPA_BYTES_PER_LINE_STR, RN, lBytesPerLine); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_BYTES_PER_LINE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_BUFFER_SIZE must be supported in order to be able to increase (if needed) the default 64KB value set + // by the WIA Compatibility Layer in the WIA Service when the driver is used with a legacy WIA 1.0 application: + // + + if (SUCCEEDED(hr)) + { + LONG lBufferSize = DEFAULT_BUFFER_SIZE; + + hr = PropertyManager.AddProperty(WIA_IPA_BUFFER_SIZE, WIA_IPA_BUFFER_SIZE_STR, RN, lBufferSize); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_BUFFER_SIZE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_AUTO_CROP + // + // The sample driver implements WIA_AUTO_CROP_SINGLE but does not support actual image cropping: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lAutoCropArray; + lAutoCropArray.Append(WIA_AUTO_CROP_DISABLED); + lAutoCropArray.Append(WIA_AUTO_CROP_SINGLE); + + hr = PropertyManager.AddProperty(WIA_IPS_AUTO_CROP, WIA_IPS_AUTO_CROP_STR, RWL, lAutoCropArray[0], lAutoCropArray[0], &lAutoCropArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_AUTO_CROP for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_OVER_SCAN + // + // The sample driver pretends to support overscanning on all directions, however the overscan settings are unfunctional: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lOverScanArray; + lOverScanArray.Append(WIA_OVER_SCAN_DISABLED); + lOverScanArray.Append(WIA_OVER_SCAN_TOP_BOTTOM); + lOverScanArray.Append(WIA_OVER_SCAN_LEFT_RIGHT); + lOverScanArray.Append(WIA_OVER_SCAN_ALL); + + hr = PropertyManager.AddProperty(WIA_IPS_OVER_SCAN, WIA_IPS_OVER_SCAN_STR, RWL, lOverScanArray[0], lOverScanArray[0], &lOverScanArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OVER_SCAN for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_OVER_SCAN_LEFT, WIA_IPS_OVER_SCAN_RIGHT, WIA_IPS_OVER_SCAN_TOP and WIA_IPS_OVER_SCAN_BOTTOM + // + // The sample driver pretends to support overscanning from 0 to 1" on all document sides, in 0.001" increments: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_OVER_SCAN_LEFT, WIA_IPS_OVER_SCAN_LEFT_STR, RWRC, 0, 0, 0, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OVER_SCAN_LEFT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_OVER_SCAN_RIGHT, WIA_IPS_OVER_SCAN_RIGHT_STR, RWRC, 0, 0, 0, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OVER_SCAN_RIGHT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_OVER_SCAN_TOP, WIA_IPS_OVER_SCAN_TOP_STR, RWRC, 0, 0, 0, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OVER_SCAN_TOP for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_OVER_SCAN_BOTTOM, WIA_IPS_OVER_SCAN_BOTTOM_STR, RWRC, 0, 0, 0, 1000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_OVER_SCAN_BOTTOM for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_COLOR_DROP + // + // The sample driver implements the color-drop properties, however it does not + // execute any actual color filtering (drop) on the test image: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lColorDropArray; + lColorDropArray.Append(WIA_COLOR_DROP_DISABLED); + lColorDropArray.Append(WIA_COLOR_DROP_RED); + lColorDropArray.Append(WIA_COLOR_DROP_GREEN); + lColorDropArray.Append(WIA_COLOR_DROP_BLUE); + lColorDropArray.Append(WIA_COLOR_DROP_RGB); + + hr = PropertyManager.AddProperty(WIA_IPS_COLOR_DROP, WIA_IPS_COLOR_DROP_STR, RWL, lColorDropArray[0], lColorDropArray[0], &lColorDropArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_COLOR_DROP for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_COLOR_DROP_MULTI: + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_COLOR_DROP_MULTI, WIA_IPS_COLOR_DROP_MULTI_STR, RN, g_lMaxDropColors); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_COLOR_DROP_MULTI for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_COLOR_DROP_RED, WIA_IPS_COLOR_DROP_GREEN and WIA_IPS_COLOR_DROP_BLUE: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_COLOR_DROP_RED, WIA_IPS_COLOR_DROP_RED_STR, RW, g_lMaxDropColors, (LONG *)&g_lDefaultDropColors[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_COLOR_DROP_RED for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_COLOR_DROP_GREEN, WIA_IPS_COLOR_DROP_GREEN_STR, RW, g_lMaxDropColors, (LONG *)&g_lDefaultDropColors[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_COLOR_DROP_GREEN for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_COLOR_DROP_BLUE, WIA_IPS_COLOR_DROP_BLUE_STR, RW, g_lMaxDropColors, (LONG *)&g_lDefaultDropColors[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_COLOR_DROP_BLUE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties specific to the Feeder item. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeFeederSpecificProperties( + _In_ BYTE* pWiasContext) + +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeFeederSpecificProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPS_DOCUMENT_HANDLING_SELECT + // + LONG lDocumentHandlingSelect = FRONT_ONLY; + LONG lDocumentHandlingSelectValidValues = FRONT_ONLY | DUPLEX; + + hr = PropertyManager.AddProperty(WIA_IPS_DOCUMENT_HANDLING_SELECT, WIA_IPS_DOCUMENT_HANDLING_SELECT_STR, RWF, lDocumentHandlingSelect, lDocumentHandlingSelectValidValues); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_DOCUMENT_HANDLING_SELECT, hr = 0x%08X", hr)); + } + + // + // WIA_IPS_SHEET_FEEDER_REGISTRATION + // + if (SUCCEEDED(hr)) + { + LONG lFeederRegistration = LEFT_JUSTIFIED; + + hr = PropertyManager.AddProperty(WIA_IPS_SHEET_FEEDER_REGISTRATION, WIA_IPS_SHEET_FEEDER_REGISTRATION_STR, RN, lFeederRegistration); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SHEET_FEEDER_REGISTRATION, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_PAGES + // + // Important: the default value for this property should be ALL_PAGES (0). + // However legacy XP applications need a WIA_IPS_PAGES > 0 in order to work. + // For this reason the default WIA_IPS_PAGES is changed to 1. Clients who need + // to transfer all available images must set WIA_IPS_PAGES to ALL_PAGES. + // + if (SUCCEEDED(hr)) + { + LONG lMaxPages = 0x7FFFFFFF; //maximum pozitive value for a signed 32-bit integer + LONG lMinPages = 0; //ALL_PAGES + LONG lDefaultPages = 1; + + hr = PropertyManager.AddProperty(WIA_IPS_PAGES, WIA_IPS_PAGES_STR, + RWR, lDefaultPages, lDefaultPages, lMinPages, lMaxPages, 1); + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PAGES, hr = 0x%08X", hr)); + } + } + + LONG lPageWidth = MAX_SCAN_AREA_WIDTH; + LONG lPageHeight = MAX_SCAN_AREA_HEIGHT; + + // + // WIA_IPS_PAGE_SIZE + // + // This sample driver supports Letter, custom and auto-detect document sizes + // + if (SUCCEEDED(hr)) + { + LONG lDefaultPageSize = WIA_PAGE_CUSTOM; + + hr = PropertyManager.AddProperty(WIA_IPS_PAGE_SIZE, WIA_IPS_PAGE_SIZE_STR, RWL, lDefaultPageSize, lDefaultPageSize, &m_lPortraitSizesArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PAGE_SIZE, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_ORIENTATION + // + // This sample driver supports only Portrait orientation + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lOrientationArray; + lOrientationArray.Append(PORTRAIT); + + hr = PropertyManager.AddProperty(WIA_IPS_ORIENTATION, WIA_IPS_ORIENTATION_STR, RWL, lOrientationArray[0], lOrientationArray[0], &lOrientationArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ORIENTATION, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_PAGE_WIDTH + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PAGE_WIDTH, WIA_IPS_PAGE_WIDTH_STR, RN, lPageWidth); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ORIENTATION, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_PAGE_HEIGHT + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PAGE_HEIGHT, WIA_IPS_PAGE_HEIGHT_STR, RN, lPageHeight); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ORIENTATION, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_JOB_SEPARATORS + // + // When job separators are enabled, the sample driver simulates a job separator page every JOB_SEPARATOR_AT_PAGE pages scanned: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lJobSeparatorsArray; + lJobSeparatorsArray.Append(WIA_SEPARATOR_DISABLED); + lJobSeparatorsArray.Append(WIA_SEPARATOR_DETECT_SCAN_CONTINUE); + lJobSeparatorsArray.Append(WIA_SEPARATOR_DETECT_SCAN_STOP); + lJobSeparatorsArray.Append(WIA_SEPARATOR_DETECT_NOSCAN_CONTINUE); + lJobSeparatorsArray.Append(WIA_SEPARATOR_DETECT_NOSCAN_STOP); + + hr = PropertyManager.AddProperty(WIA_IPS_JOB_SEPARATORS, WIA_IPS_JOB_SEPARATORS_STR, RWL, lJobSeparatorsArray[0], lJobSeparatorsArray[0], &lJobSeparatorsArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_JOB_SEPARATORS, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_LONG_DOCUMENT + // + // The sample driver implemenmts the property but does not implement the actual functionality: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lLongDocArray; + lLongDocArray.Append(WIA_LONG_DOCUMENT_DISABLED); + lLongDocArray.Append(WIA_LONG_DOCUMENT_ENABLED); + lLongDocArray.Append(WIA_LONG_DOCUMENT_SPLIT); + + hr = PropertyManager.AddProperty(WIA_IPS_LONG_DOCUMENT, WIA_IPS_LONG_DOCUMENT_STR, RWL, lLongDocArray[0], lLongDocArray[0], &lLongDocArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_LONG_DOCUMENT, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_BLANK_PAGES + // + // The sample driver implements the property but does not implement actual blank page detection functionality: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lBlankPagesArray; + lBlankPagesArray.Append(WIA_BLANK_PAGE_DETECTION_DISABLED); + lBlankPagesArray.Append(WIA_BLANK_PAGE_DISCARD); + lBlankPagesArray.Append(WIA_BLANK_PAGE_JOB_SEPARATOR); + + hr = PropertyManager.AddProperty(WIA_IPS_BLANK_PAGES, WIA_IPS_BLANK_PAGES_STR, RWL, lBlankPagesArray[0], lBlankPagesArray[0], &lBlankPagesArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BLANK_PAGES, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_BLANK_PAGES_SENSITIVITY + // + // This sample driver reports a range of supported values (which are not functional) + // between 0 and 10 inclusive, with 5 being the default sensitivity: + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_BLANK_PAGES_SENSITIVITY, WIA_IPS_BLANK_PAGES_SENSITIVITY_STR, RWR, 5, 5, 1, 10, 1); + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BLANK_PAGES_SENSITIVITY, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_MULTI_FEED + // + // When multi-feed detection is enabled, the sample driver simulates a multi-feed condition every MULTI_FEED_AT_PAGE pages scanned: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lMultiFeedArray; + lMultiFeedArray.Append(WIA_MULTI_FEED_DETECT_DISABLED); + lMultiFeedArray.Append(WIA_MULTI_FEED_DETECT_STOP_ERROR); + lMultiFeedArray.Append(WIA_MULTI_FEED_DETECT_STOP_SUCCESS); + lMultiFeedArray.Append(WIA_MULTI_FEED_DETECT_CONTINUE); + + hr = PropertyManager.AddProperty(WIA_IPS_MULTI_FEED, WIA_IPS_MULTI_FEED_STR, RWL, lMultiFeedArray[0], lMultiFeedArray[0], &lMultiFeedArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MULTI_FEED, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_MULTI_FEED_SENSITIVITY + // + // This sample driver reports a range of supported values (which are not functional) + // between 0 and 10 inclusive, with 5 being the default sensitivity: + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_MULTI_FEED_SENSITIVITY, WIA_IPS_MULTI_FEED_SENSITIVITY_STR, RWR, 5, 5, 1, 10, 1); + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MULTI_FEED_SENSITIVITY, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_ALARM + // + // This sample driver does pretend to support one kind of audible alarm (beep) to signal + // when a multi-feed conditions is detected, not functional: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lAlarmArray; + lAlarmArray.Append(WIA_ALARM_NONE); + lAlarmArray.Append(WIA_ALARM_BEEP1); + + hr = PropertyManager.AddProperty(WIA_IPS_ALARM, WIA_IPS_ALARM_STR, RWL, lAlarmArray[0], lAlarmArray[0], &lAlarmArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ALARM, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_SCAN_AHEAD: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lScanAheadArray; + lScanAheadArray.Append(WIA_SCAN_AHEAD_DISABLED); + lScanAheadArray.Append(WIA_SCAN_AHEAD_ENABLED); + + hr = PropertyManager.AddProperty(WIA_IPS_SCAN_AHEAD, WIA_IPS_SCAN_AHEAD_STR, RWL, lScanAheadArray[0], lScanAheadArray[0], &lScanAheadArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SCAN_AHEAD, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_SCAN_AHEAD_CAPACITY: + // + if (SUCCEEDED(hr)) + { + ULONG ulScanAheadCapacity = 0; //undefined + + hr = PropertyManager.AddPropertyUL(WIA_IPS_SCAN_AHEAD_CAPACITY, WIA_IPS_SCAN_AHEAD_CAPACITY_STR, RN, ulScanAheadCapacity); + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SCAN_AHEAD_CAPACITY, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_FEEDER_CONTROL + // + // The sample driver pretents to support manual feeder motor control + // (the WIA_COMMAND_START_FEEDER and the WIA_COMMAND_STOP_FEEDER commands): + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lFeederControlArray; + lFeederControlArray.Append(WIA_FEEDER_CONTROL_AUTO); + lFeederControlArray.Append(WIA_FEEDER_CONTROL_MANUAL); + + hr = PropertyManager.AddProperty(WIA_IPS_FEEDER_CONTROL, WIA_IPS_FEEDER_CONTROL_STR, RWL, lFeederControlArray[0], lFeederControlArray[0], &lFeederControlArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SCAN_AHEAD, hr = 0x%08X", hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for feeder, hr = 0x%08X", hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties specific to the Imprinter and Endorser items. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* nDocumentHandlingSelect - IMPRINTER or ENDORSER (defined in wiadef.h) +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeImprinterEndorserProperties( + _In_ BYTE* pWiasContext, + UINT nDocumentHandlingSelect) +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if ((!pWiasContext) || ((IMPRINTER != nDocumentHandlingSelect) && (ENDORSER != nDocumentHandlingSelect))) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeImprinterEndorserProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPS_PRINTER_ENDORSER + // + // This sample driver pretends to have an imprinter on the front side of the feeder and an endorser on the back side + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lPrinterEndorserArray; + lPrinterEndorserArray.Append(WIA_PRINTER_ENDORSER_DISABLED); + lPrinterEndorserArray.Append(WIA_PRINTER_ENDORSER_AUTO); + lPrinterEndorserArray.Append((IMPRINTER == nDocumentHandlingSelect) ? WIA_PRINTER_ENDORSER_FEEDER_FRONT : WIA_PRINTER_ENDORSER_FEEDER_BACK); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER, WIA_IPS_PRINTER_ENDORSER_STR, RWL, lPrinterEndorserArray[0], lPrinterEndorserArray[0], &lPrinterEndorserArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_ORDER + // + // The sample imprinter operates after scan, the sample endorser operates before scan + // + if (SUCCEEDED(hr)) + { + LONG lPrinterEndorserOrder = (IMPRINTER == nDocumentHandlingSelect) ? WIA_PRINTER_ENDORSER_AFTER_SCAN : WIA_PRINTER_ENDORSER_BEFORE_SCAN; + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_ORDER, WIA_IPS_PRINTER_ENDORSER_ORDER_STR, RN, lPrinterEndorserOrder); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_ORDER for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_COUNTER + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_COUNTER , WIA_IPS_PRINTER_ENDORSER_COUNTER_STR, RWRC, 0, 0, 0, 0xFFFFFFFF, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_COUNTER for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + } + + // + // WIA_IPS_PRINTER_ENDORSER_STEP + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_STEP, WIA_IPS_PRINTER_ENDORSER_STEP_STR, RWRC, 1, 1, 1, 0xFFFFFFFF, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_STEP for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + } + + // + // WIA_IPS_PRINTER_ENDORSER_XOFFSET and WIA_IPS_PRINTER_ENDORSER_YOFFSET + // + // This sample driver pretends to support from 0" to 3" inclusive imprinter and endorser offsets, in 0.001" step increments + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_XOFFSET, WIA_IPS_PRINTER_ENDORSER_XOFFSET_STR, RWRC, 0, 0, 0, 3000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_XOFFSET for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + else + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_YOFFSET, WIA_IPS_PRINTER_ENDORSER_YOFFSET_STR, RWRC, 0, 0, 0, 3000, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_YOFFSET for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_ROTATION + // + // This sample driver pretends to support all standard 90' rotation values for its imprinter and endorser units + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lRotationArray; + lRotationArray.Append(PORTRAIT); + lRotationArray.Append(LANDSCAPE); + lRotationArray.Append(ROT180); + lRotationArray.Append(ROT270); + + hr = PropertyManager.AddProperty(WIA_IPS_ROTATION, WIA_IPS_ROTATION_STR, RWL, lRotationArray[0], lRotationArray[0], &lRotationArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ROTATION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_NUM_LINES + // + // This sample driver pretends that supports only one line of text for the imprinter and for the endorser + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_NUM_LINES, WIA_IPS_PRINTER_ENDORSER_NUM_LINES_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_NUM_LINES for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_STRING + // + if (SUCCEEDED(hr)) + { + BSTR bstrPrinterEndorser = SysAllocString((IMPRINTER == nDocumentHandlingSelect) ? L"Sample imprinter text" : L"Sample endorser text"); + if (bstrPrinterEndorser) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_STRING, WIA_IPS_PRINTER_ENDORSER_STRING_STR, RW, bstrPrinterEndorser); + + SysFreeString(bstrPrinterEndorser); + } + else + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Could not allocate memory for the the WIA_IPS_PRINTER_ENDORSER_STRING property value, hr = 0x%08X", hr)); + } + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_STRING for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS + // + if (SUCCEEDED(hr)) + { + BSTR bstrValidChars = SysAllocString((IMPRINTER == nDocumentHandlingSelect) ? SAMPLE_IMPRINTER_VALID_CHARS : SAMPLE_ENDORSER_VALID_CHARS); + if (bstrValidChars) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS, WIA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS_STR, RN, bstrValidChars); + + SysFreeString(bstrValidChars); + bstrValidChars = NULL; + } + else + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Could not allocate memory for the the IA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS property value, hr = 0x%08X", hr)); + } + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_VALID_CHARACTERS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_VALID_FORMAT_SPECIFIERS + // + // This sample driver implements this optional property only for the imprinter + // where it implements a sub-set of all the possible standard values. + // + if (SUCCEEDED(hr) && (IMPRINTER == nDocumentHandlingSelect)) + { + LONG lFormatSpecs[] = { + WIA_PRINT_DATE, + WIA_PRINT_YEAR, + WIA_PRINT_MONTH, + WIA_PRINT_DAY, + WIA_PRINT_WEEK_DAY, + WIA_PRINT_TIME_24H, + WIA_PRINT_HOUR_24H, + WIA_PRINT_MINUTE, + WIA_PRINT_SECOND, + WIA_PRINT_PAGE_COUNT}; + ULONG ulFormatSpecs = ARRAYSIZE(lFormatSpecs); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_VALID_FORMAT_SPECIFIERS, WIA_IPS_PRINTER_ENDORSER_VALID_FORMAT_SPECIFIERS_STR, RN, ulFormatSpecs, lFormatSpecs); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_VALID_FORMAT_SPECIFIERS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_PADDING + // + // This sample driver does pretend to support all imprinter/endorser padding values but does not really apply padding: + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lPaddingArray; + lPaddingArray.Append(WIA_PRINT_PADDING_NONE); + lPaddingArray.Append(WIA_PRINT_PADDING_ZERO); + lPaddingArray.Append(WIA_PRINT_PADDING_BLANK); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_PADDING, WIA_IPS_PRINTER_ENDORSER_PADDING_STR, RWL, lPaddingArray[0], lPaddingArray[0], &lPaddingArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_PADDING for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_FONT_TYPE + // + // This sample driver does support all font type values but does not apply font type changes. + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lFontTypeArray; + lFontTypeArray.Append(WIA_PRINT_FONT_NORMAL); + lFontTypeArray.Append(WIA_PRINT_FONT_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_ITALIC_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_ITALIC_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_ITALIC); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL_ITALIC_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL_ITALIC_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_SMALL_ITALIC); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE_ITALIC_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE_ITALIC_EXTRA_BOLD); + lFontTypeArray.Append(WIA_PRINT_FONT_LARGE_ITALIC); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_FONT_TYPE, WIA_IPS_PRINTER_ENDORSER_FONT_TYPE_STR, RWL, lFontTypeArray[0], lFontTypeArray[0], &lFontTypeArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_FONT_TYPE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_CHARACTER_ROTATION + // + // This sample driver pretends to support all possible values, but does not actually apply any character rotation. + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lCharRotatationArray; + lCharRotatationArray.Append(PORTRAIT); + lCharRotatationArray.Append(LANDSCAPE); + lCharRotatationArray.Append(ROT180); + lCharRotatationArray.Append(ROT270); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_CHARACTER_ROTATION, WIA_IPS_PRINTER_ENDORSER_CHARACTER_ROTATION_STR, + RWL, lCharRotatationArray[0], lCharRotatationArray[0], &lCharRotatationArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_CHARACTER_ROTATION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + + // + // WIA_IPS_PRINTER_ENDORSER_MAX_CHARACTERS + // + // This sample driver pretends to support a maximum number of characters of 0xFFFFFFFF (unrealistic) for the imprinter and endorser. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_MAX_CHARACTERS, WIA_IPS_PRINTER_ENDORSER_MAX_CHARACTERS_STR, RN, 0xFFFFFFFF); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_MAX_CHARACTERS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_INK + // + // This sample driver hard-codes a value of 50% (half capacity remaining) for the imprinter and endorser ink. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_INK, WIA_IPS_PRINTER_ENDORSER_INK_STR, RN, 50); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_INK for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_TEXT_UPLOAD + // + // This sample driver reports to support imprinter/endorser text upload to show how an upload + // transfer is to be executed, however the uploaded data is not retained/applied. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_TEXT_UPLOAD, WIA_IPS_PRINTER_ENDORSER_TEXT_UPLOAD_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_TEXT_UPLOAD for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_TEXT_DOWNLOAD + // + // This sample driver reports to support imprinter/endorser text download to show how a download + // transfer is to be executed, however the downloaded data is always the same/fixed, and is not + // modified to match WIA_IPS_PRINTER_ENDORSER_STRING. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_TEXT_DOWNLOAD, WIA_IPS_PRINTER_ENDORSER_TEXT_DOWNLOAD_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_TEXT_DOWNLOAD for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_GRAPHICS, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_POSITION + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lPositionArray; + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_DEVICE_DEFAULT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_LEFT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_RIGHT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_TOP); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_BOTTOM); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_TOP_LEFT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_TOP_RIGHT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_BOTTOM_LEFT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_BOTTOM_RIGHT); + lPositionArray.Append(WIA_PRINTER_ENDORSER_GRAPHICS_BACKGROUND); + + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_POSITION, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_POSITION_STR, RWL, lPositionArray[0], lPositionArray[0], &lPositionArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ROTATION for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_WIDTH + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_HEIGHT + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_WIDTH + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_HEIGHT + // + // This sample driver supports a fixed/predefined graphics size that match the sample imprinter/endorser test image + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_WIDTH, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_WIDTH_STR, RN, IMPRINTER_MIN_WIDTH); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_WIDTH for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_WIDTH, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_WIDTH_STR, RN, IMPRINTER_MAX_WIDTH); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_WIDTH for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_HEIGHT, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_HEIGHT_STR, RN, IMPRINTER_MIN_HEIGHT); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MIN_HEIGHT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_HEIGHT, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_HEIGHT_STR, RN, IMPRINTER_MAX_HEIGHT); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_MAX_HEIGHT for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_MAX_GRAPHICS + // + // This sample driver pretends to support a maximum number of graphics of 1 for its imprinter and endorser. + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_PRINTER_ENDORSER_MAX_GRAPHICS, WIA_IPS_PRINTER_ENDORSER_MAX_GRAPHICS_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_MAX_GRAPHICS for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_UPLOAD + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_UPLOAD, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_UPLOAD_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_UPLOAD for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPS_PRINTER_ENDORSER_GRAPHICS_DOWNLOAD + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddProperty(WIA_IPS_PRINTER_ENDORSER_GRAPHICS_DOWNLOAD, WIA_IPS_PRINTER_ENDORSER_GRAPHICS_DOWNLOAD_STR, RN, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PRINTER_ENDORSER_GRAPHICS_DOWNLOAD for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_DATATYPE + // + // The sample driver supports 1-bpp BW graphics data for the imprinter and the endorser. + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lDataTypeArray; + lDataTypeArray.Append(WIA_DATA_DITHER); + + hr = PropertyManager.AddProperty(WIA_IPA_DATATYPE, WIA_IPA_DATATYPE_STR, RWL, lDataTypeArray[0], lDataTypeArray[0], &lDataTypeArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_DATATYPE for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_DEPTH + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lDepthArray; + lDepthArray.Append(1); + + hr = PropertyManager.AddProperty(WIA_IPA_DEPTH , WIA_IPA_DEPTH_STR, RWLC, lDepthArray[0], lDepthArray[0], &lDepthArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_DEPTH for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_CHANNELS_PER_PIXEL + // + if (SUCCEEDED(hr)) + { + LONG lChannelsPerPixel = 1; + + hr = PropertyManager.AddProperty(WIA_IPA_CHANNELS_PER_PIXEL, WIA_IPA_CHANNELS_PER_PIXEL_STR, RN, lChannelsPerPixel); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_CHANNELS_PER_PIXEL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // WIA_IPA_BITS_PER_CHANNEL + // + if (SUCCEEDED(hr)) + { + LONG lBitsPerChannel = 1; + + hr = PropertyManager.AddProperty(WIA_IPA_BITS_PER_CHANNEL, WIA_IPA_BITS_PER_CHANNEL_STR, RN, lBitsPerChannel); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPA_BITS_PER_CHANNEL for item %u, hr = 0x%08X", nDocumentHandlingSelect, hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for item %u, hr = 0x%08X", + nDocumentHandlingSelect, hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties specific to the Barcode Reader item. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeBarcodeReaderProperties( + _In_ BYTE* pWiasContext) +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeBarcodeReaderProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPS_BARCODE_READER + // + // This sample driver pretends to support a barcode reader device installed on the front feeder side + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lBarcodeReaderArray; + lBarcodeReaderArray.Append(WIA_BARCODE_READER_DISABLED); + lBarcodeReaderArray.Append(WIA_BARCODE_READER_AUTO); + lBarcodeReaderArray.Append(WIA_BARCODE_READER_FEEDER_FRONT); + + hr = PropertyManager.AddProperty(WIA_IPS_BARCODE_READER, WIA_IPS_BARCODE_READER_STR, RWL, lBarcodeReaderArray[0], lBarcodeReaderArray[0], &lBarcodeReaderArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BARCODE_READER, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_MAXIMUM_BARCODES_PER_PAGE + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_MAXIMUM_BARCODES_PER_PAGE, WIA_IPS_MAXIMUM_BARCODES_PER_PAGE_STR, RWR, 0, 0, 0, 10, 1); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MAXIMUM_BARCODES_PER_PAGE, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_BARCODE_SEARCH_DIRECTION + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lBarcodeSearchArray; + lBarcodeSearchArray.Append(WIA_BARCODE_AUTO_SEARCH); + lBarcodeSearchArray.Append(WIA_BARCODE_HORIZONTAL_SEARCH); + lBarcodeSearchArray.Append(WIA_BARCODE_VERTICAL_SEARCH); + lBarcodeSearchArray.Append(WIA_BARCODE_HORIZONTAL_VERTICAL_SEARCH); + lBarcodeSearchArray.Append(WIA_BARCODE_VERTICAL_HORIZONTAL_SEARCH); + + hr = PropertyManager.AddProperty(WIA_IPS_BARCODE_SEARCH_DIRECTION, WIA_IPS_BARCODE_SEARCH_DIRECTION_STR, RWL, lBarcodeSearchArray[0], lBarcodeSearchArray[0], &lBarcodeSearchArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BARCODE_SEARCH_DIRECTION, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_MAXIMUM_BARCODE_SEARCH_RETRIES + // + // This sample driver pretends to support no retries (range containing only the value 0) + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_MAXIMUM_BARCODE_SEARCH_RETRIES, WIA_IPS_MAXIMUM_BARCODE_SEARCH_RETRIES_STR, RWR, 0, 0, 0, 0, 0); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MAXIMUM_BARCODE_SEARCH_RETRIES, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_BARCODE_SEARCH_TIMEOUT + // + if (SUCCEEDED(hr)) + { + hr = PropertyManager.AddPropertyUL(WIA_IPS_BARCODE_SEARCH_TIMEOUT, WIA_IPS_BARCODE_SEARCH_TIMEOUT_STR, RWR, 0, 0, 0, 100, 10); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_BARCODE_SEARCH_TIMEOUT, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_SUPPORTED_BARCODE_TYPES + // + // This sample driver pretends to support a multitude of barcode types. This driver + // ignores this setting when delivering its hard-coded sample barcodes but uses + // WIA_IPS_SUPPORTED_BARCODE_TYPES to validate WIA_IPS_ENABLED_BARCODE_TYPES + // + if (SUCCEEDED(hr)) + { + ULONG ulBarcodeTypes = ARRAYSIZE(g_lSupportedBarcodeTypes); + + hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTED_BARCODE_TYPES, WIA_IPS_SUPPORTED_BARCODE_TYPES_STR, RN, ulBarcodeTypes, (LONG *)&g_lSupportedBarcodeTypes[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SUPPORTED_BARCODE_TYPES, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_ENABLED_BARCODE_TYPES + // + // By default when barcode detection is enabled there are 3 barcodes enabled, which + // happen to match the sample, hard-coded, barcode metadata for this driver + // + if (SUCCEEDED(hr)) + { + LONG lDefaultEnabledBarcodeTypes[] = { WIA_BARCODE_UPCA, WIA_BARCODE_CODABAR, WIA_BARCODE_CODE39_FULLASCII }; + ULONG ulBarcodeTypes = ARRAYSIZE(lDefaultEnabledBarcodeTypes); + + hr = PropertyManager.AddProperty(WIA_IPS_ENABLED_BARCODE_TYPES, WIA_IPS_ENABLED_BARCODE_TYPES_STR, RW, ulBarcodeTypes, &lDefaultEnabledBarcodeTypes[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ENABLED_BARCODE_TYPES, hr = 0x%08X", hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for the barcode reader item, hr = 0x%08X", hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties specific to the Patch Code Reader item. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializePatchCodeReaderProperties( + _In_ BYTE* pWiasContext) +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializePatchCodeReaderProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPS_PATCH_CODE_READER + // + // This sample driver pretends to support a patch code reader device installed + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lPatchCodeReaderArray; + lPatchCodeReaderArray.Append(WIA_PATCH_CODE_READER_DISABLED); + lPatchCodeReaderArray.Append(WIA_PATCH_CODE_READER_AUTO); + + hr = PropertyManager.AddProperty(WIA_IPS_PATCH_CODE_READER, WIA_IPS_PATCH_CODE_READER_STR, RWL, lPatchCodeReaderArray[0], lPatchCodeReaderArray[0], &lPatchCodeReaderArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_PATCH_CODE_READER, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_SUPPORTED_PATCH_CODE_TYPES + // + // This sample driver pretends to support a multitude of barcode types. This driver + // ignores this setting when delivering its hard-coded sample barcodes but uses + // WIA_IPS_SUPPORTED_PATCH_CODE_TYPES to validate WIA_IPS_ENABLED_PATCH_CODE_TYPES + // + if (SUCCEEDED(hr)) + { + ULONG ulPatchCodeTypes = ARRAYSIZE(g_lSupportedPatchCodeTypes); + + hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTED_PATCH_CODE_TYPES, WIA_IPS_SUPPORTED_PATCH_CODE_TYPES_STR, RN, ulPatchCodeTypes, (LONG *)&g_lSupportedPatchCodeTypes[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_SUPPORTED_PATCH_CODE_TYPES, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_ENABLED_PATCH_CODE_TYPES + // + // By default when barcode detection is enabled there are 2 patch codes enabled, which + // happen to match the sample, hard-coded, patch code metadata for this driver + // + if (SUCCEEDED(hr)) + { + LONG lDefaultEnabledPatchCodeTypes[] = { WIA_PATCH_CODE_2, WIA_PATCH_CODE_3 }; + ULONG ulPatchCodeTypes = ARRAYSIZE(lDefaultEnabledPatchCodeTypes); + + hr = PropertyManager.AddProperty(WIA_IPS_ENABLED_PATCH_CODE_TYPES, WIA_IPS_ENABLED_PATCH_CODE_TYPES_STR, RW, ulPatchCodeTypes, &lDefaultEnabledPatchCodeTypes[0]); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ENABLED_PATCH_CODE_TYPES, hr = 0x%08X", hr)); + } + } + + // + // WIA_IPS_ALARM + // + // This sample driver does pretend to support one kind of audible alarm (beep) to signal + // when a path code is successfully detected + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lAlarmArray; + lAlarmArray.Append(WIA_ALARM_NONE); + lAlarmArray.Append(WIA_ALARM_BEEP1); + + hr = PropertyManager.AddProperty(WIA_IPS_ALARM, WIA_IPS_ALARM_STR, RWL, lAlarmArray[0], lAlarmArray[0], &lAlarmArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_ALARM, hr = 0x%08X", hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for the patch code reader item, hr = 0x%08X", hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes the properties specific to the MICR Reader item. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeMicrReaderProperties( + _In_ BYTE* pWiasContext) +{ + HRESULT hr = S_OK; + CWIAPropertyManager PropertyManager; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::InitializeMicrReaderProperties, invalid parameter, hr = 0x%08X", hr)); + } + + WIAEX_TRACE_BEGIN; + + // + // WIA_IPS_MICR_READER + // + // This sample driver pretends to support a MICR reader device installed on the front feeder side + // + if (SUCCEEDED(hr)) + { + CBasicDynamicArray<LONG> lMICRReaderArray; + lMICRReaderArray.Append(WIA_MICR_READER_DISABLED); + lMICRReaderArray.Append(WIA_MICR_READER_AUTO); + lMICRReaderArray.Append(WIA_MICR_READER_FEEDER_FRONT); + + hr = PropertyManager.AddProperty(WIA_IPS_MICR_READER, WIA_IPS_MICR_READER_STR, RWL, lMICRReaderArray[0], lMICRReaderArray[0], &lMICRReaderArray); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Failed to initialize WIA_IPS_MICR_READER, hr = 0x%08X", hr)); + } + } + + // + // Apply the property changes to the current session's Application Item Tree: + // + + if (SUCCEEDED(hr)) + { + hr = PropertyManager.SetItemProperties(pWiasContext); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA item properties for the MICR reader item, hr = 0x%08X", hr)); + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Initializes WIA_FORMAT_INFO arrays needed for IWiaMiniDrv::drvGetWiaFormatInfo +* +* Parameters: +* +* None +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT CWiaDriver::InitializeFormatInfoArrays() +{ + HRESULT hr = S_OK; + WIA_FORMAT_INFO tFormatInfo = {}; + + // + // This sample driver supports the same WIA_FORMAT_INFO array for Root, Flatbed, Feeder and Auto items: + // + // { WiaImgFmt_BMP, TYMED_FILE } + // { WiaImgFmt_EXIF, TYMED_FILE } + // { WiaImgFmt_RAW, TYMED_FILE } + // + + m_tFormatInfo.Destroy(); + + tFormatInfo.guidFormatID = WiaImgFmt_BMP; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfo.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_EXIF; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfo.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_RAW; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfo.Append(tFormatInfo); + + // + // The Imprinter and Endorser items support: + // + // { WiaImgFmt_CSV, TYMED_FILE } + // { WiaImgFmt_TXT, TYMED_FILE } + // { WiaImgFmt_BMP, TYMED_FILE } + // + + m_tFormatInfoImprinterEndorser.Destroy(); + + tFormatInfo.guidFormatID = WiaImgFmt_CSV; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoImprinterEndorser.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_TXT; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoImprinterEndorser.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_BMP; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoImprinterEndorser.Append(tFormatInfo); + + // + // The Barcode Reader item supports: + // + // { WiaImgFmt_XMLBAR, TYMED_FILE } + // { WiaImgFmt_RAWBAR, TYMED_FILE } + // + + m_tFormatInfoBarcodeReader.Destroy(); + + tFormatInfo.guidFormatID = WiaImgFmt_XMLBAR; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoBarcodeReader.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_RAWBAR; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoBarcodeReader.Append(tFormatInfo); + + // + // The Patch Code Reader item supports: + // + // { WiaImgFmt_XMLPAT, TYMED_FILE } + // { WiaImgFmt_RAWPAT, TYMED_FILE } + // + + m_tFormatInfoPatchCodeReader.Destroy(); + + tFormatInfo.guidFormatID = WiaImgFmt_XMLPAT; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoPatchCodeReader.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_RAWPAT; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoPatchCodeReader.Append(tFormatInfo); + + // + // The MICR Reader item supports: + // + // { WiaImgFmt_XMLMIC, TYMED_FILE } + // { WiaImgFmt_RAWMIC, TYMED_FILE } + // + + m_tFormatInfoMicrReader.Destroy(); + + tFormatInfo.guidFormatID = WiaImgFmt_XMLMIC; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoMicrReader.Append(tFormatInfo); + + tFormatInfo.guidFormatID = WiaImgFmt_RAWMIC; + tFormatInfo.lTymed = TYMED_FILE; + m_tFormatInfoMicrReader.Append(tFormatInfo); + + return hr; +} + +/**************************************************************************\ +* +* Updates the following image information properties in auto-detect color mode. +* Because this sample driver does not support cropping (scan region changes) +* and supports only a single/fixed scan resolution this function is not needed +* to be executed in other situations: +* +* WIA_IPA_PIXELS_PER_LINE +* WIA_IPA_NUMBER_OF_LINES +* WIA_IPA_BYTES_PER_LINE +* WIA_IPA_CHANNELS_PER_PIXEL +* WIA_IPA_RAW_CHANNELS_PER_PIXEL +* +* Note that these properties are not implemented/available on the Auto item. +* +* Parameters: +* +* pWiasContext - pointer to the item context +* lDataType - data type; if set to WIA_DATA_AUTO the +* function reads the current WIA_IPA_DATATYPE. +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ +HRESULT CWiaDriver::UpdateImageInfoProperties( + _In_ BYTE *pWiasContext, + LONG lDataType) +{ + HRESULT hr = S_OK; + GUID guidItemCategory = WIA_CATEGORY_ROOT; + LONG lDepth = 8; + LONG lChannelsPerPixel = 1; + LONG lCompression = WIA_COMPRESSION_NONE; + GUID guidFormat = WiaImgFmt_UNDEFINED; + LONG lXExtent = 0; + LONG lYExtent = 0; + LONG lPixelsPerLine = 0; + LONG lNumberOfLines = 0; + LONG lBytesPerLine = 0; + + WIAEX_TRACE_BEGIN; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "CWiaDriver::UpdateImageInfoProperties, invalid parameter, hr = 0x%08X", hr)); + } + + // + // Read WIA_IPA_ITEM_CATEGORY to identify the current item: + // + if (SUCCEEDED(hr)) + { + hr = wiasReadPropGuid(pWiasContext, WIA_IPA_ITEM_CATEGORY, &guidItemCategory, NULL, TRUE); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_ITEM_CATEGORY, hr = 0x%08X", hr)); + } + } + + // + // Cannot validate image information properties on the Root or Auto items: + // + if (SUCCEEDED(hr) && ((IsEqualGUID(WIA_CATEGORY_ROOT, guidItemCategory)) || + (IsEqualGUID(WIA_CATEGORY_AUTO, guidItemCategory)))) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Functionality not supported on this item, hr = 0x%08X", hr)); + } + + // + // If a data type is not specified, read WIA_IPA_DATATYPE: + // + if (SUCCEEDED(hr)) + { + if (WIA_DATA_AUTO == lDataType) + { + LONG lActualDataType = WIA_DATA_GRAYSCALE; + + hr = wiasReadPropLong(pWiasContext, WIA_IPA_DATATYPE, &lActualDataType, NULL, TRUE); + if (SUCCEEDED(hr)) + { + if (WIA_DATA_AUTO == lActualDataType) + { + WIAEX_ERROR((g_hInst, "Unspecified data type! Considering 8-bpp grayscale (default) and trying to continue")); + lDepth = 8; + } + else + { + lDepth = (WIA_DATA_COLOR == lActualDataType) ? 24 : 8; + } + } + else + { + WIAEX_ERROR((g_hInst, "Error reading current WIA_IPA_DATA_TYPE, hr = 0x%08X", hr)); + } + } + else + { + lDepth = (WIA_DATA_COLOR == lDataType) ? 24 : 8; + } + } + + // + // Check the current WIA_IPA_COMPRESSION: + // + if (SUCCEEDED(hr)) + { + 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)); + } + } + + // + // Check the current WIA_IPA_FORMAT: + // + 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)); + } + } + + // + // Check the current WIA_IPS_XEXTENT and WIA_IPS_YTEXTENT: + // + 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)) + { + // + // The number of bytes per line include the padding necessary to make each uncompressed + // line (DIB or Raw) DWORD aligned. When data is compressed the number of bytes per line + // calculated here reflects the original uncompressed image: + // + lPixelsPerLine = lXExtent; + lNumberOfLines = lYExtent; + lBytesPerLine = BytesPerLine(lPixelsPerLine, lDepth); + + WIAS_TRACE((g_hInst, "Image information: %u PPL, %u lines, %u BPL (compression: %u)", + lPixelsPerLine, lNumberOfLines, lBytesPerLine, lCompression)); + } + + // + // Update the following properties, supported for backwards compatibility (with WIA 1.0 + // and TWAIN) on the Flatbed and Feeder item but not on the new Auto item: + // + // 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 that must match WIA_IPA_PIXELS_PER_LINE and WIA_IPA_DEPTH + // + 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)); + } + } + + // + // Update WIA_IPA_CHANNELS_PER_PIXEL and WIA_IPA_RAW_BITS_PER_CHANNEL top match the bit depth. + // Note that this saple driver does not need to update WIA_IPA_BITS_PER_CHANNEL, and that + // WIA_IPA_DEPTH and WIA_IPA_DATA_TYPE are updated during validation (see ValidateFormatProperties): + // + + 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)); + } + } + + if (SUCCEEDED(hr)) + { + BYTE bRawBitsPerChannel[3] = {}; + + 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)); + } + } + + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Updates the globally stored (per driver instance) scan available item +* name indicating that this item is marked for data transfer due to a +* device initiated scan operation, and/or the scanner is not in a scan +* available state. +* +* Parameters: +* +* wszInputSource - a WIA item name as the name of the input source, +* NULL to reset the value to an empty string. +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ +HRESULT CWiaDriver::UpdateScanAvailableItemName( + _In_opt_ LPCWSTR wszInputSource) +{ + HRESULT hr = S_OK; + + // + // Clear the current name: + // + if (m_bstrScanAvailableItem) + { + SysFreeString(m_bstrScanAvailableItem); + m_bstrScanAvailableItem = NULL; + } + + // + // Identify the input source and prepare the value containing the apropriate item name: + // + if (wszInputSource) + { + if (!wcscmp(WIA_DRIVER_FEEDER_NAME, wszInputSource)) + { + WIAS_TRACE((g_hInst, "Scan available from feeder (%ws)", wszInputSource)); + m_bstrScanAvailableItem = SysAllocString(WIA_DRIVER_FEEDER_NAME); + } + else if (!wcscmp(WIA_DRIVER_FLATBED_NAME, wszInputSource)) + { + WIAS_TRACE((g_hInst, "Scan available from flatbed (%ws)", wszInputSource)); + m_bstrScanAvailableItem = SysAllocString(WIA_DRIVER_FLATBED_NAME); + } + else + { + WIAS_TRACE((g_hInst, "Scan available from unknown input source (%ws) - information not recorded", + wszInputSource)); + m_bstrScanAvailableItem = SysAllocString(L""); + } + } + else + { + // + // A trace message is avoided here on purpose - the following message, if enabled, + // would be visible both when initializing a new AIT Root with no scan available + // input source recorded -and- when resetting the scan available soure information + // from within IWiaMiniDrv::drvAcquireItemData before executing a new scan job. + // + m_bstrScanAvailableItem = SysAllocString(L""); + } + + if (!m_bstrScanAvailableItem) + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Failed to update the scan available item name, out of memory, hr = 0x%08X", hr)); + } + + return hr; +} + +/**************************************************************************\ +* +* Updates the WIA_DPS_SCAN_AVAILABLE_ITEM property at real-time when an +* application attempts to read a property from its AIT Root item. We cannot +* make this update immediately following a notification that a device initiated +* scan is available because the event comes globally, outside of any application +* session context (possibly at a time when no application session exists). +* +* WARNING: must not be called on other items than Root (WiaItemTypeRoot). +* +* Parameters: +* +* pWiasContext - pointer to the item context +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ +HRESULT CWiaDriver::UpdateScanAvailableItemProperty( + _In_ BYTE *pWiasContext) +{ + HRESULT hr = S_OK; + + if (!pWiasContext) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + // + // If no value is initialized yet, initialize it now to an + // empty string meaning "no scan available source recorded": + // + if (SUCCEEDED(hr) && (!m_bstrScanAvailableItem)) + { + m_bstrScanAvailableItem = SysAllocString(L""); + if (!m_bstrScanAvailableItem) + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Failed to initialize an empty string in lieu of a scan available item name, hr = 0x%08X", hr)); + } + } + + // + // Update the WIA_DPS_SCAN_AVAILABLE_ITEM property: + // + if (SUCCEEDED(hr)) + { + hr = wiasWritePropStr(pWiasContext, WIA_DPS_SCAN_AVAILABLE_ITEM, m_bstrScanAvailableItem); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "wiasWritePropStr(WIA_DPS_SCAN_AVAILABLE_ITEM, '%ws') failed, hr = 0x%08X", m_bstrScanAvailableItem, hr)); + } + } + + return hr; +} + +/**************************************************************************\ +* +* Retrieves standard WIA page sizes that fit in the specified scan area +* dimensions considering the specified orientation. +* +* Parameters: +* +* lMaxWidth - maximum width of the total scan area, in 1/1000" +* lMaxHeight - maximum height of the total scan area, in 1/1000" +* lMinWidth - minimum width of the total scan area, in 1/1000" +* lMinHeight - minimum height of the total scan area, in 1/1000" +* bPortrait - TRUE for portrait, FALSE for landscape orientation +* arrayPageSizes - reference for array where to return page sizes +* +* Return Value: +* +* The number of page sizes found +* +\**************************************************************************/ + +LONG CWiaDriver::GetValidPageSizes( + LONG lMaxWidth, + LONG lMaxHeight, + LONG lMinWidth, + LONG lMinHeight, + BOOL bPortrait, + CBasicDynamicArray<LONG>& arrayPageSizes) +{ + LONG lNumPageSizesFound = 0; + LONG lNumKnownPageSizes = sizeof(g_DefinedPageSizeCombinations) / sizeof(g_DefinedPageSizeCombinations[0]); + + // + // Do not erase page sizes already added to the array, + // append new values that are not yet in the array: + // + // arrayPageSizes.Destroy(); + // + + for (LONG i = 0; i < lNumKnownPageSizes; i++) + { + if (bPortrait) + { + if ((g_DefinedPageSizeCombinations[i].m_lPageWidth <= lMaxWidth) && + (g_DefinedPageSizeCombinations[i].m_lPageHeight <= lMaxHeight) && + (g_DefinedPageSizeCombinations[i].m_lPageWidth >= lMinWidth) && + (g_DefinedPageSizeCombinations[i].m_lPageHeight >= lMinHeight)) + { + if (-1 == arrayPageSizes.Find(g_DefinedPageSizeCombinations[i].m_lPageSize)) + { + arrayPageSizes.Append(g_DefinedPageSizeCombinations[i].m_lPageSize); + } + } + } + else + { + if ((g_DefinedPageSizeCombinations[i].m_lPageWidth <= lMaxHeight) && + (g_DefinedPageSizeCombinations[i].m_lPageHeight <= lMaxWidth) && + (g_DefinedPageSizeCombinations[i].m_lPageWidth >= lMinHeight) && + (g_DefinedPageSizeCombinations[i].m_lPageHeight >= lMinWidth)) + { + if (-1 == arrayPageSizes.Find(g_DefinedPageSizeCombinations[i].m_lPageSize)) + { + arrayPageSizes.Append(g_DefinedPageSizeCombinations[i].m_lPageSize); + } + } + } + } + + lNumPageSizesFound = arrayPageSizes.Size(); + + return lNumPageSizesFound; +} + +/**************************************************************************\ +* +* Returns the width and height for the specified standard page size, +* in 1/1000", according with the indicated orientation +* +* Parameters: +* +* lPageSize - the page size to return the dimensions for +* bPortrait - TRUE for portait orientation, FALSE for landscape +* lPageWidth - reference for variable to receive the page width +* lPageHeight - reference for variable to receive the page height +* Return Value: +* +* S_OK if successful, E_INVALIDARG if no such standard page size is found +* +\**************************************************************************/ + +HRESULT CWiaDriver::GetPageDimensions( + LONG lPageSize, + BOOL bPortrait, + LONG& lPageWidth, + LONG& lPageHeight) +{ + HRESULT hr = E_INVALIDARG; + LONG lNumKnownPageSizes = sizeof(g_DefinedPageSizeCombinations) / sizeof(g_DefinedPageSizeCombinations[0]); + + for (LONG i = 0; i < lNumKnownPageSizes; i++) + { + if (g_DefinedPageSizeCombinations[i].m_lPageSize == lPageSize) + { + if (bPortrait) + { + lPageWidth = g_DefinedPageSizeCombinations[i].m_lPageWidth; + lPageHeight = g_DefinedPageSizeCombinations[i].m_lPageHeight; + } + else + { + lPageWidth = g_DefinedPageSizeCombinations[i].m_lPageHeight; + lPageHeight = g_DefinedPageSizeCombinations[i].m_lPageWidth; + } + + hr = S_OK; + break; + } + } + + return hr; +} |
