HRESULT CWiaDriver::InitializeFlatbedFeederProperties()

in wia/ProdScan/InitProp.cpp [570:1293]


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;
}