Sample Code

Windows Driver Samples/ Windows Image Acquisition (WIA) Driver Samples/ C++/ wiadriverex/ usd/ wiahelpers.cpp/

/**************************************************************************
*
*  Copyright (c) 2003  Microsoft Corporation
*
*  Title: wiahelpers.cpp
*
*  Description: This file contains a number of helper functions
*               for child item creation etc.
*
***************************************************************************/
#include "stdafx.h"
#include <strsafe.h>

static FILM_FRAME g_FilmFrames[] = { { 36, 27,  222, 167 },
                                     { 36, 221, 222, 167 },
                                     { 37, 418, 222, 167 },
                                     { 37, 614, 221, 172 } };


/**
 * This function creates a full WIA item name
 * from a given WIA item name.
 *
 * The new full item name is created by concatinating
 * the WIA item name with the parent's full item name.
 *
 * (e.g. 0000\Root + MyItem = 0000\Root\MyItem)
 *
 * @param pParent IWiaDrvItem interface of the parent WIA driver item
 * @param bstrItemName
 *                Name of the WIA item
 * @param pbstrFullItemName
 *                Returned full item name.  This parameter
 *                cannot be NULL.
 * @return S_OK - if successful
 *         E_XXXXXXXX - failure result
 */
HRESULT MakeFullItemName(
    _In_    IWiaDrvItem *pParent,
    _In_    BSTR        bstrItemName,
    _Out_   BSTR        *pbstrFullItemName)
{
    HRESULT hr = S_OK;
    if((pParent)&&(bstrItemName)&&(pbstrFullItemName))
    {
        BSTR bstrParentFullItemName = NULL;
        hr = pParent->GetFullItemName(&bstrParentFullItemName);
        if(SUCCEEDED(hr))
        {
            CBasicStringWide cswFullItemName;
            cswFullItemName.Format(TEXT("%ws\\%ws"),bstrParentFullItemName,bstrItemName);
            *pbstrFullItemName = SysAllocString(cswFullItemName.String());
            if(*pbstrFullItemName)
            {
                hr = S_OK;
            }
            else
            {
                hr = E_OUTOFMEMORY;
                WIAS_ERROR((g_hInst, "Failed to allocate memory for BSTR full item name, hr = 0x%lx",hr));
            }
            SysFreeString(bstrParentFullItemName);
            bstrParentFullItemName = NULL;
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get full item name from parent IWiaDrvItem, hr = 0x%lx",hr));
        }
    }
    else
    {
        hr = E_INVALIDARG;
        WIAS_ERROR((g_hInst, "Invalid parameters were passed, hr = 0x%lx",hr));
    }
    return hr;
}

/**
 * This function creates a WIA child item
 *
 * @param wszItemName
 *                   Item name
 * @param pIWiaMiniDrv
 *                   WIA minidriver interface
 * @param pParent Parent's WIA driver item interface
 * @param lItemFlags Item flags
 * @param guidItemCategory
 *                   Item category
 * @param ppChild Pointer to the newly created child item
 * @param wszStoragePath
 *                   Storage data path
 * @return
 */
HRESULT CreateWIAChildItem(
    _In_            LPOLESTR    wszItemName,
    _In_            IWiaMiniDrv *pIWiaMiniDrv,
    _In_            IWiaDrvItem *pParent,
                    LONG        lItemFlags,
                    GUID        guidItemCategory,
    _Out_opt_       IWiaDrvItem **ppChild,
    _In_opt_        PCWSTR      wszStoragePath)
{
    HRESULT hr = E_INVALIDARG;
    if((wszItemName)&&(pIWiaMiniDrv)&&(pParent))
    {
        BSTR        bstrItemName        = SysAllocString(wszItemName);
        BSTR        bstrFullItemName    = NULL;
        IWiaDrvItem *pIWiaDrvItem       = NULL;

        if (bstrItemName)
        {
            hr = MakeFullItemName(pParent,bstrItemName,&bstrFullItemName);
            if(SUCCEEDED(hr))
            {
                WIA_DRIVER_ITEM_CONTEXT *pWiaDriverItemContext = NULL;
                hr = wiasCreateDrvItem(lItemFlags,
                                    bstrItemName,
                                    bstrFullItemName,
                                    pIWiaMiniDrv,
                                    sizeof(WIA_DRIVER_ITEM_CONTEXT),
                                    (BYTE **)&pWiaDriverItemContext,
                                    &pIWiaDrvItem);
                if(SUCCEEDED(hr))
                {
                    pWiaDriverItemContext->ulFeederTransferCount = 0;
                    pWiaDriverItemContext->guidItemCategory = guidItemCategory;
                    if(wszStoragePath)
                    {
                        pWiaDriverItemContext->bstrStorageDataPath = SysAllocString(wszStoragePath);
                        if(!pWiaDriverItemContext->bstrStorageDataPath)
                        {
                            hr = E_OUTOFMEMORY;
                            WIAS_ERROR((g_hInst, "Failed to allocate memory for BSTR storage item path, hr = 0x%lx",hr));
                        }
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = pIWiaDrvItem->AddItemToFolder(pParent);
                        if(FAILED(hr))
                        {
                            WIAS_ERROR((g_hInst, "Failed to add the new WIA item (%ws) to the specified parent item, hr = 0x%lx",bstrFullItemName,hr));
                            pIWiaDrvItem->Release();
                            pIWiaDrvItem = NULL;
                        }

                        //
                        // If a child iterface pointer parameter was specified, then the caller
                        // expects to have the newly created child interface pointer returned to
                        // them. (do not release the newly created item, in this case)
                        //

                        if(ppChild)
                        {
                            *ppChild        = pIWiaDrvItem;
                            pIWiaDrvItem    = NULL;
                        }
                        else if (pIWiaDrvItem)
                        {
                            //
                            // The newly created child has been added to the tree, and is no longer
                            // needed.  Release it.
                            //

                            pIWiaDrvItem->Release();
                            pIWiaDrvItem = NULL;
                        }
                    }
                }
                else
                {
                    WIAS_ERROR((g_hInst, "Failed to create the new WIA driver item, hr = 0x%lx",hr));
                }

                SysFreeString(bstrItemName);
                bstrItemName = NULL;
                SysFreeString(bstrFullItemName);
                bstrFullItemName = NULL;
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to create the new WIA item's full item name, hr = 0x%lx",hr));
            }
        }
        else
        {
            //
            // Failed to allocate memory for bstrItemName.
            //
            hr = E_OUTOFMEMORY;
            WIAS_ERROR((g_hInst, "Failed to allocate memory for BSTR storage item name"));
        }

    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function creates a WIA flatbed item.  WIA
 * flatbed items will automatically have the
 * WIA category setting of WIA_CATEGORY_FLATBED.
 *
 * @param wszItemName
 *                   Item name
 * @param pIWiaMiniDrv
 *                   WIA minidriver interface
 * @param pParent Parent's WIA driver item interface
 * @return
 */
HRESULT CreateWIAFlatbedItem(
    _In_        LPOLESTR    wszItemName,
    _In_        IWiaMiniDrv *pIWiaMiniDrv,
    _In_        IWiaDrvItem *pParent)
{
    LONG lItemFlags  = WiaItemTypeImage | WiaItemTypeTransfer | WiaItemTypeFile | WiaItemTypeProgrammableDataSource | WiaItemTypeFolder;
    return CreateWIAChildItem(wszItemName,pIWiaMiniDrv,pParent,lItemFlags, WIA_CATEGORY_FLATBED,NULL);
}

/**
 * This function creates a WIA feeder item.  WIA
 * feeder items will automatically have the
 * WIA category setting of WIA_CATEGORY_FEEDER.
 *
 * @param wszItemName
 *                   Item name
 * @param pIWiaMiniDrv
 *                   WIA minidriver interface
 * @param pParent Parent's WIA driver item interface
 * @return
 */
HRESULT CreateWIAFeederItem(
    _In_        LPOLESTR    wszItemName,
    _In_        IWiaMiniDrv *pIWiaMiniDrv,
    _In_        IWiaDrvItem *pParent)
{
    LONG lItemFlags  = WiaItemTypeImage | WiaItemTypeTransfer | WiaItemTypeFile | WiaItemTypeProgrammableDataSource;
    return CreateWIAChildItem(wszItemName,pIWiaMiniDrv,pParent,lItemFlags, WIA_CATEGORY_FEEDER,NULL);
}

/**
 * This function creates a WIA film item.  WIA
 * film items will automatically have the
 * WIA category setting of WIA_CATEGORY_FILM.
 *
 * @param wszItemName
 *                   Item name
 * @param pIWiaMiniDrv
 *                   WIA minidriver interface
 * @param pParent Parent's WIA driver item interface
 * @return
 */
HRESULT CreateWIAFilmItem(
    _In_        LPOLESTR    wszItemName,
    _In_        IWiaMiniDrv *pIWiaMiniDrv,
    _In_        IWiaDrvItem *pParent)
{
    LONG        lItemFlags  = WiaItemTypeImage | WiaItemTypeTransfer | WiaItemTypeFolder | WiaItemTypeProgrammableDataSource;
    IWiaDrvItem *pChild     = NULL;
    HRESULT hr = S_OK;
    hr = CreateWIAChildItem(wszItemName,pIWiaMiniDrv,pParent,lItemFlags, WIA_CATEGORY_FILM,&pChild);
    if(SUCCEEDED(hr))
    {
        if(pChild)
        {
            lItemFlags = WiaItemTypeImage | WiaItemTypeTransfer | WiaItemTypeFile | WiaItemTypeProgrammableDataSource;
            hr = CreateWIAChildItem(L"Frame1",pIWiaMiniDrv,pChild,lItemFlags, WIA_CATEGORY_FILM,NULL);
            if(SUCCEEDED(hr))
            {
                hr = CreateWIAChildItem(L"Frame2",pIWiaMiniDrv,pChild,lItemFlags, WIA_CATEGORY_FILM,NULL);
            }
            if(SUCCEEDED(hr))
            {
                hr = CreateWIAChildItem(L"Frame3",pIWiaMiniDrv,pChild,lItemFlags, WIA_CATEGORY_FILM,NULL);
            }
            if(SUCCEEDED(hr))
            {
                hr = CreateWIAChildItem(L"Frame4",pIWiaMiniDrv,pChild,lItemFlags, WIA_CATEGORY_FILM,NULL);
            }

            pChild->Release();
            pChild = NULL;
        }
    }
    return hr;
}

/**
 * This function creates the main sample WIA storage item.
 * WIA storage items should have either the WIA category
 * of WIA_CATEGORY_FINISHED_FILE (for stored image files)
 * or WIA_CATEGORY_FOLDER (for storage folder items).
 *
 * @param wszItemName
 *                   Item name
 * @param pIWiaMiniDrv
 *                   WIA minidriver interface
 * @param pParent
 *                   Parent's WIA driver item interface
 * @return
 */
HRESULT CreateWIAStorageItem(
    _In_    LPOLESTR    wszItemName,
    _In_    IWiaMiniDrv *pIWiaMiniDrv,
    _In_    IWiaDrvItem *pParent,
    _In_    const WCHAR * wszStoragePath)
{
    LONG lItemFlags  = WiaItemTypeFolder | WiaItemTypeStorage;

    IWiaDrvItem *pChild = NULL;
    HRESULT     hr      = S_OK;

    hr = CreateWIAChildItem(wszItemName, pIWiaMiniDrv, pParent, lItemFlags, WIA_CATEGORY_FOLDER, &pChild);
    if (SUCCEEDED(hr))
    {
        if (pChild)
        {
            lItemFlags = WiaItemTypeTransfer | WiaItemTypeFile;

            //TBD: This function only searches the first level for
            //     content.  It ignores any directories found.

            CBasicStringWide cswSearchPath = wszStoragePath;
            cswSearchPath += L"\\*.*";

            WIN32_FIND_DATA *pFindData = (WIN32_FIND_DATA*) LocalAlloc(LPTR, sizeof(WIN32_FIND_DATA));

            if(!pFindData)
            {
                hr = E_OUTOFMEMORY;
            }
            else
            {
                HANDLE hFindFile = FindFirstFile(cswSearchPath.String(),pFindData);
                if(INVALID_HANDLE_VALUE != hFindFile)
                {
                    do
                    {
                        if(!(pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                        {
                            CBasicStringWide cswFileDataPath   = wszStoragePath;
                            cswFileDataPath                     += L"\\";
                            cswFileDataPath                     += pFindData->cFileName;
                            hr = CreateWIAChildItem(pFindData->cFileName,
                                                    pIWiaMiniDrv,
                                                    pChild,
                                                    lItemFlags,
                                                    WIA_CATEGORY_FINISHED_FILE,
                                                    NULL,
                                                    cswFileDataPath.String());
                            if(FAILED(hr))
                            {
                                WIAS_ERROR((g_hInst, "Failed to create WIA child storage item, hr = 0x%lx",hr));
                                break;
                            }
                        }

                    } while(FindNextFile(hFindFile,pFindData));

                    FindClose(hFindFile);
                }

                LocalFree(pFindData);
                pFindData = NULL;
            }

            pChild->Release();
            pChild = NULL;
        }
    }

    return hr;
}

/**
 * This function initializes any root item properties
 * needed for this WIA driver.
 *
 * @param pWiasContext
 *               Pointer to the WIA item context
 * @return
 */
HRESULT InitializeRootItemProperties(
    _In_    BYTE        *pWiasContext)
{
    HRESULT hr = E_INVALIDARG;
    if(pWiasContext)
    {
        CWIAPropertyManager PropertyManager;
        GUID guidItemCategory = WIA_CATEGORY_ROOT;
        hr = PropertyManager.AddProperty(WIA_IPA_ITEM_CATEGORY, WIA_IPA_ITEM_CATEGORY_STR, RN, guidItemCategory);
        if(FAILED(hr))
        {
            WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ITEM_CATEGORY property to the property manager, hr = 0x%lx", hr));
        }

        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))
            {
                WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ACCESS_RIGHTS property to the property manager, hr = 0x%lx", hr));
            }
        }

        if(SUCCEEDED(hr))
        {
            LONG lDocumentHandlingCapabilities = FLAT | FEED | DUP | FILM_TPA | STOR;
            hr = PropertyManager.AddProperty(WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES,
                WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES_STR , RN, lDocumentHandlingCapabilities);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "Failed to add WIA_DPS_DOCUMENT_HANDLING_CAPABILITIES property to the property manager, hr = 0x%lx", hr));
            }
        }

        if(SUCCEEDED(hr))
        {
            LONG lDocumentHandlingStatus = FEED_READY | FILM_TPA_READY | STORAGE_READY | FLAT_READY;
            hr = PropertyManager.AddProperty(WIA_DPS_DOCUMENT_HANDLING_STATUS,
                WIA_DPS_DOCUMENT_HANDLING_STATUS_STR, RN, lDocumentHandlingStatus);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "Failed to add WIA_DPS_DOCUMENT_HANDLING_STATUS property to the property manager, hr = 0x%lx", hr));
            }
        }

        if (SUCCEEDED(hr))
        {
            BSTR bstrFirmware = SysAllocString(L"0.9.1");
            if ( bstrFirmware )
            {
                hr = PropertyManager.AddProperty(WIA_DPA_FIRMWARE_VERSION, WIA_DPA_FIRMWARE_VERSION_STR, RN, bstrFirmware);
                if (FAILED(hr))
                {
                    WIAS_ERROR((g_hInst, "Failed to add WIA_DPA_FIRMWARE_VERSION to prop manager, hr = 0x%lx", hr));
                }
                SysFreeString(bstrFirmware);
            }
            else
            {
                hr = E_OUTOFMEMORY;
            }
        }

        if(SUCCEEDED(hr))
        {
            hr = PropertyManager.SetItemProperties(pWiasContext);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA root item properties, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ITEM_CATEGORY property to the property manager, hr = 0x%lx",hr));
        }

    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function initializes child item properties
 * needed for this WIA driver.  The uiResourceID parameter
 * determines what image properties will be used.
 *
 * @param pWiasContext
 *                  Pointer to the WIA item context
 * @param hInstance HINSTANCE of the resource location containing uiResourceIDs
 * @param uiResourceID
 *                  Resource ID of a bitmap resource loaded as source data
 *                  and a source of WIA item properties.
 *                  FALSE - Child item WIA properties will be added to the item.
 * @return
 */
HRESULT InitializeWIAItemProperties(
    _In_    BYTE        *pWiasContext,
    _In_    HINSTANCE   hInstance,
            UINT        uiResourceID)
{
    // WARNING: No checks for failed CBasicDynamicArray::Append() calls.
    // For robustness, error handling should be added.

    HRESULT hr = E_INVALIDARG;
    BOOL bRootFilm = FALSE;

    if((pWiasContext)&&(hInstance))
    {
        //
        // Reset the feeder image transfer count:
        //
        WIA_DRIVER_ITEM_CONTEXT *pWiaDriverItemContext = NULL;
        hr = wiasGetDriverItemPrivateContext(pWiasContext, (BYTE**)&pWiaDriverItemContext);
        if ((SUCCEEDED(hr)) && (!pWiaDriverItemContext))
        {
            hr = E_POINTER;
        }
        if (SUCCEEDED(hr))
        {
            pWiaDriverItemContext->ulFeederTransferCount = 0;
        }

        if (SUCCEEDED(hr))
        {
            CWIAPropertyManager PropertyManager;

            LONG lXPosition         = 0;
            LONG lYPosition         = 0;
            LONG lXExtent           = 0;
            LONG lYExtent           = 0;
            LONG lPixWidth          = 0;
            LONG lPixHeight         = 0;
            LONG lXResolution       = 75;  // Our sample images are 75 dpi
            LONG lYResolution       = 75;  // Our sample images are 75 dpi
            LONG lHorizontalSize    = 0;
            LONG lVerticalSize      = 0;
            LONG lMinHorizontalSize = 1; //0.001"
            LONG lMinVerticalSize   = 1; //0.001"
            LONG lItemType          = 0;

            HBITMAP hBitmap = static_cast<HBITMAP>(LoadImage(hInstance, MAKEINTRESOURCE(uiResourceID), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION));

            if (hBitmap)
            {
                Bitmap *pBitmap = Bitmap::FromHBITMAP(hBitmap, NULL);

                if (pBitmap)
                {
                    lXExtent        = (LONG)pBitmap->GetWidth();
                    lYExtent        = (LONG)pBitmap->GetHeight();
                    lPixWidth       = lXExtent;
                    lPixHeight      = lYExtent;
                    lHorizontalSize = ConvertTo1000thsOfAnInch(lXExtent, lXResolution);
                    lVerticalSize   = ConvertTo1000thsOfAnInch(lYExtent, lYResolution);

                    SAFE_DELETE (pBitmap);
                }

                DeleteObject(hBitmap);
                hBitmap = NULL;
            }

            //
            // Set coordinates for fixed frames
            //
            if (IDB_FILM == uiResourceID)
            {
                ULONG   ulFrame      = NO_FIXED_FRAME;
                BSTR    bstrItemName = NULL;
                //  Get the item name
                hr = wiasReadPropStr(pWiasContext, WIA_IPA_ITEM_NAME, &bstrItemName, NULL, TRUE);

                if (S_OK == hr)
                {
                    if (!lstrcmp(bstrItemName, L"Frame1"))
                    {
                        ulFrame = 0;
                    }
                    else if (!lstrcmp(bstrItemName, L"Frame2"))
                    {
                        ulFrame = 1;
                    }
                    else if (!lstrcmp(bstrItemName, L"Frame3"))
                    {
                        ulFrame = 2;
                    }
                    else if (!lstrcmp(bstrItemName, L"Frame4"))
                    {
                        ulFrame = 3;
                    }
                    else
                    {
                        bRootFilm = TRUE;
                    }

                    if (ulFrame != NO_FIXED_FRAME)
                    {
                        lXPosition = g_FilmFrames[ulFrame].XPOS;
                        lYPosition = g_FilmFrames[ulFrame].YPOS;
                        lXExtent   = g_FilmFrames[ulFrame].XEXTENT;
                        lYExtent   = g_FilmFrames[ulFrame].YEXTENT;
                    }

                    SysFreeString(bstrItemName);
                    bstrItemName = NULL;
                }
            }

            hr = wiasGetItemType(pWiasContext,&lItemType);
            if(SUCCEEDED(hr))
            {
                if(lItemType & WiaItemTypeGenerated)
                {
                    WIAS_TRACE((g_hInst,"WIA item was created by application."));
                }
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to get the WIA item type, hr = 0x%lx",hr));
            }

            //
            // Add all common item properties first
            //

            if((lXExtent)&&(lYExtent)&&(lXResolution)&&(lYResolution)&&(lHorizontalSize)&&(lVerticalSize))
            {
                LONG lAccessRights = WIA_ITEM_READ;
                hr = PropertyManager.AddProperty(WIA_IPA_ACCESS_RIGHTS ,WIA_IPA_ACCESS_RIGHTS_STR ,RF, lAccessRights, lAccessRights);

                if(SUCCEEDED(hr))
                {
                    LONG lOpticalXResolution = lXResolution;
                    hr = PropertyManager.AddProperty(WIA_IPS_OPTICAL_XRES ,WIA_IPS_OPTICAL_XRES_STR ,RN,lOpticalXResolution);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lOpticalYResolution = lYResolution;
                    hr = PropertyManager.AddProperty(WIA_IPS_OPTICAL_YRES ,WIA_IPS_OPTICAL_YRES_STR ,RN,lOpticalYResolution);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lPreviewArray;
                    lPreviewArray.Append(WIA_FINAL_SCAN);
                    lPreviewArray.Append(WIA_PREVIEW_SCAN);
                    hr = PropertyManager.AddProperty(WIA_IPS_PREVIEW ,WIA_IPS_PREVIEW_STR ,RWLC,lPreviewArray[0],lPreviewArray[0],&lPreviewArray);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lShowPreviewControl = WIA_SHOW_PREVIEW_CONTROL;
                    hr = PropertyManager.AddProperty(WIA_IPS_SHOW_PREVIEW_CONTROL ,WIA_IPS_SHOW_PREVIEW_CONTROL_STR ,RN,lShowPreviewControl);
                }

                if(SUCCEEDED(hr))
                {
                    //
                    // Support creation of child items underneath the base flatbed item:
                    //
                    BOOL bChildItemCreation = FALSE;

                    if(uiResourceID == IDB_FLATBED)
                    {
                        LONG lItemFlags = 0;
                        hr = wiasReadPropLong(pWiasContext, WIA_IPA_ITEM_FLAGS, &lItemFlags, NULL, TRUE);
                        if ((S_OK == hr) && (lItemFlags & WiaItemTypeFolder))
                        {
                            bChildItemCreation = TRUE;
                        }
                    }

                    hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION_STR, RN, bChildItemCreation);
                }

                if((uiResourceID == IDB_FLATBED) || (uiResourceID == IDB_FILM))
                {
                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MAX_HORIZONTAL_SIZE ,WIA_IPS_MAX_HORIZONTAL_SIZE_STR ,RN,lHorizontalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MAX_VERTICAL_SIZE ,WIA_IPS_MAX_VERTICAL_SIZE_STR ,RN,lVerticalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MIN_HORIZONTAL_SIZE ,WIA_IPS_MIN_HORIZONTAL_SIZE_STR ,RN,lMinHorizontalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MIN_VERTICAL_SIZE ,WIA_IPS_MIN_VERTICAL_SIZE_STR ,RN,lMinVerticalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        LONG lSegmentation = (IDB_FLATBED == uiResourceID) ? WIA_USE_SEGMENTATION_FILTER : WIA_DONT_USE_SEGMENTATION_FILTER;
                        hr = PropertyManager.AddProperty(WIA_IPS_SEGMENTATION ,WIA_IPS_SEGMENTATION_STR ,RN, lSegmentation);
                    }

                    if (SUCCEEDED(hr) && (IDB_FILM == uiResourceID))
                    {
                        if (bRootFilm)
                        {
                            CBasicDynamicArray<LONG> lFilmScanModeArray;
                            lFilmScanModeArray.Append(WIA_FILM_COLOR_SLIDE);
                            hr = PropertyManager.AddProperty(WIA_IPS_FILM_SCAN_MODE, WIA_IPS_FILM_SCAN_MODE_STR, RWL, lFilmScanModeArray[0], lFilmScanModeArray[0], &lFilmScanModeArray);
                        }
                    }
                }
                else if(uiResourceID == IDB_FEEDER)
                {
                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MAX_HORIZONTAL_SIZE ,WIA_IPS_MAX_HORIZONTAL_SIZE_STR ,RN,lHorizontalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MAX_VERTICAL_SIZE ,WIA_IPS_MAX_VERTICAL_SIZE_STR ,RN,lVerticalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MIN_HORIZONTAL_SIZE ,WIA_IPS_MIN_HORIZONTAL_SIZE_STR ,RN,lMinHorizontalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        hr = PropertyManager.AddProperty(WIA_IPS_MIN_VERTICAL_SIZE ,WIA_IPS_MIN_VERTICAL_SIZE_STR ,RN,lMinVerticalSize);
                    }

                    if(SUCCEEDED(hr))
                    {
                        LONG lSheetFeederRegistration = LEFT_JUSTIFIED;
                        hr = PropertyManager.AddProperty(WIA_IPS_SHEET_FEEDER_REGISTRATION ,WIA_IPS_SHEET_FEEDER_REGISTRATION_STR ,RN,lSheetFeederRegistration);
                    }

                    if(SUCCEEDED(hr))
                    {
                        //
                        // Just basic duplex mode supported (no single back side scan):
                        //
                        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(SUCCEEDED(hr))
                    {
                        LONG lMaxPages            = 100;
                        LONG lDefaultPagesSetting = 1;
                        LONG lPages               = 1;
                        hr = PropertyManager.AddProperty(WIA_IPS_PAGES ,WIA_IPS_PAGES_STR ,RWR,lDefaultPagesSetting,lDefaultPagesSetting,0,lMaxPages,lPages);
                    }

                    //
                    // For the Feeder item implement support for WIA_IPS_PAGE_SIZE (just AUTO supported for now,
                    // in a real case standard and possibly document sizes would have to be added here):
                    //
                    if (SUCCEEDED(hr))
                    {
                        LONG lAutoPageSize = WIA_PAGE_AUTO;
                        hr = PropertyManager.AddProperty(WIA_IPS_PAGE_SIZE, WIA_IPS_PAGE_SIZE_STR, RN, lAutoPageSize);

                        CBasicDynamicArray<LONG> lPageSizeArray;
                        lPageSizeArray.Append(WIA_PAGE_AUTO);
                        hr = PropertyManager.AddProperty(WIA_IPS_PAGE_SIZE, WIA_IPS_PAGE_SIZE_STR, RWL, lPageSizeArray[0], lPageSizeArray[0], &lPageSizeArray);
                    }

                    //
                    // WIA_IPS_PAGE_WIDTH and WIA_IPS_PAGE_HEIGHT are required for feeder item
                    //
                    if (SUCCEEDED(hr)) {
                        hr = PropertyManager.AddProperty(WIA_IPS_PAGE_WIDTH, WIA_IPS_PAGE_WIDTH_STR, RN, lHorizontalSize);
                    }

                    if (SUCCEEDED(hr)) {
                        hr = PropertyManager.AddProperty(WIA_IPS_PAGE_HEIGHT, WIA_IPS_PAGE_HEIGHT_STR, RN, lVerticalSize);
                    }

                    if (SUCCEEDED(hr)) {
                        CBasicDynamicArray<LONG> lOrientationArray;
                        lOrientationArray.Append(PORTRAIT);
                        lOrientationArray.Append(LANSCAPE);
                        lOrientationArray.Append(ROT180);
                        lOrientationArray.Append(ROT270);
                        hr = PropertyManager.AddProperty(WIA_IPS_ORIENTATION, WIA_IPS_ORIENTATION_STR, RWL, lOrientationArray[0], lOrientationArray[0], &lOrientationArray);
                    }
                }

                if(SUCCEEDED(hr))
                {
                    LONG lCurrentIntent             = WIA_INTENT_NONE;
                    LONG lCurrentIntentValidValues  = WIA_INTENT_IMAGE_TYPE_COLOR | WIA_INTENT_MINIMIZE_SIZE | WIA_INTENT_MAXIMIZE_QUALITY;
                    hr = PropertyManager.AddProperty(WIA_IPS_CUR_INTENT ,WIA_IPS_CUR_INTENT_STR ,RWF,lCurrentIntent,lCurrentIntentValidValues);
                }

                if(SUCCEEDED(hr))
                {
                    GUID guidItemCategory = WIA_CATEGORY_FLATBED;
                    switch(uiResourceID)
                    {
                    case IDB_FLATBED:
                        guidItemCategory = WIA_CATEGORY_FLATBED;
                        break;
                    case IDB_FEEDER:
                        guidItemCategory = WIA_CATEGORY_FEEDER;
                        break;
                    case IDB_FILM:
                        guidItemCategory = WIA_CATEGORY_FILM;
                        break;
                    default:
                        guidItemCategory = GUID_NULL;
                        break;
                    }

                    hr = PropertyManager.AddProperty(WIA_IPA_ITEM_CATEGORY,WIA_IPA_ITEM_CATEGORY_STR,RN,guidItemCategory);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lXResolutionArray;
                    lXResolutionArray.Append(lXResolution);
                    hr = PropertyManager.AddProperty(WIA_IPS_XRES ,WIA_IPS_XRES_STR ,RWLC,lXResolutionArray[0],lXResolutionArray[0],&lXResolutionArray);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lYResolutionArray;
                    lYResolutionArray.Append(lYResolution);
                    hr = PropertyManager.AddProperty(WIA_IPS_YRES ,WIA_IPS_YRES_STR ,RWLC,lYResolutionArray[0],lYResolutionArray[0],&lYResolutionArray);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_XPOS, WIA_IPS_XPOS_STR, RWRC, lXPosition, lXPosition, 0, lPixWidth - 1, 1);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_YPOS, WIA_IPS_YPOS_STR, RWRC, lYPosition, lYPosition, 0, lPixHeight -1, 1);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_XEXTENT ,WIA_IPS_XEXTENT_STR ,RWRC, lXExtent, lXExtent, 1, lPixWidth - lXPosition, 1);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_YEXTENT ,WIA_IPS_YEXTENT_STR ,RWRC, lYExtent, lYExtent, 1, lPixHeight - lYPosition, 1);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lRotationArray;
                    lRotationArray.Append(PORTRAIT);
                    lRotationArray.Append(LANSCAPE);
                    lRotationArray.Append(ROT180);
                    lRotationArray.Append(ROT270);

                    hr = PropertyManager.AddProperty(WIA_IPS_ROTATION ,WIA_IPS_ROTATION_STR ,RWLC,lRotationArray[0],lRotationArray[0],&lRotationArray);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_DESKEW_X ,WIA_IPS_DESKEW_X_STR ,RWRC,0,0,0,lXExtent,1);
                }

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.AddProperty(WIA_IPS_DESKEW_Y ,WIA_IPS_DESKEW_Y_STR ,RWRC,0,0,0,lYExtent,1);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lBrightness = 0;
                    hr = PropertyManager.AddProperty(WIA_IPS_BRIGHTNESS,WIA_IPS_BRIGHTNESS_STR,RWRC,lBrightness,lBrightness,-1000,1000,1);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lContrast = 0;
                    hr = PropertyManager.AddProperty(WIA_IPS_CONTRAST ,WIA_IPS_CONTRAST_STR ,RWRC,lContrast,lContrast,-1000,1000,1);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lErrorHandler             = ERROR_HANDLING_NONE;
                    LONG lErrorHandlerValidValues  = ERROR_HANDLING_WARMING_UP | ERROR_HANDLING_COVER_OPEN | ERROR_HANDLING_PRIVATE_ERROR | ERROR_HANDLING_UNHANDLED_STATUS | ERROR_HANDLING_UNHANDLED_ERROR;

                    hr = PropertyManager.AddProperty(MY_WIA_ERROR_HANDLING_PROP ,MY_WIA_ERROR_HANDLING_PROP_STR ,RWF,lErrorHandler,lErrorHandlerValidValues);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lTestFilterArray;
                    lTestFilterArray.Append(0);
                    lTestFilterArray.Append(1);

                    hr = PropertyManager.AddProperty(MY_TEST_FILTER_PROP ,MY_TEST_FILTER_PROP_STR ,RWLC,lTestFilterArray[0],lTestFilterArray[0],&lTestFilterArray);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lItemSize = 0;
                    hr = PropertyManager.AddProperty(WIA_IPA_ITEM_SIZE ,WIA_IPA_ITEM_SIZE_STR ,RN,lItemSize);
                }

                if(SUCCEEDED(hr))
                {
                    // TBD: This property is assuming that the source image is color.  Should be changed to be
                    //      more dynamic.
                    CBasicDynamicArray<LONG> lDataTypeArray;
                    lDataTypeArray.Append(WIA_DATA_COLOR);
                    hr = PropertyManager.AddProperty(WIA_IPA_DATATYPE ,WIA_IPA_DATATYPE_STR ,RWL,lDataTypeArray[0],lDataTypeArray[0],&lDataTypeArray);
                }

                if(SUCCEEDED(hr))
                {
                    // TBD: This property is assuming that the source image is 24-bit color.  Should be changed to be
                    //      more dynamic.
                    CBasicDynamicArray<LONG> lBitDepthArray;
                    lBitDepthArray.Append(24);
                    hr = PropertyManager.AddProperty(WIA_IPA_DEPTH ,WIA_IPA_DEPTH_STR ,RWLC,lBitDepthArray[0],lBitDepthArray[0],&lBitDepthArray);
                }

                if(SUCCEEDED(hr))
                {
                    GUID guidPreferredFormat = WiaImgFmt_BMP;
                    hr = PropertyManager.AddProperty(WIA_IPA_PREFERRED_FORMAT ,WIA_IPA_PREFERRED_FORMAT_STR ,RN,guidPreferredFormat);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<GUID> guidFormatArray;
                    guidFormatArray.Append(WiaImgFmt_BMP);
                    guidFormatArray.Append(WiaImgFmt_RAW);
                    hr = PropertyManager.AddProperty(WIA_IPA_FORMAT ,WIA_IPA_FORMAT_STR ,RWL,guidFormatArray[0],guidFormatArray[0],&guidFormatArray);
                }

                if(SUCCEEDED(hr))
                {
                    CBasicDynamicArray<LONG> lCompressionArray;
                    lCompressionArray.Append(WIA_COMPRESSION_NONE);
                    hr = PropertyManager.AddProperty(WIA_IPA_COMPRESSION ,WIA_IPA_COMPRESSION_STR ,RWL, lCompressionArray[0], lCompressionArray[0], &lCompressionArray);
                }

                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(SUCCEEDED(hr))
                {
                    // TBD: This property is assuming that the source image is 24-bit color and has 3 channels.  Should be changed to be
                    //      more dynamic.
                    LONG lChannelsPerPixel = 3;
                    hr = PropertyManager.AddProperty(WIA_IPA_CHANNELS_PER_PIXEL ,WIA_IPA_CHANNELS_PER_PIXEL_STR ,RN,lChannelsPerPixel);
                }

                if(SUCCEEDED(hr))
                {
                    // TBD: This property is assuming that the source image is 24-bit color and has 8 bits per channel.  Should be changed to be
                    //      more dynamic.
                    LONG lBitsPerChannel = 8;
                    hr = PropertyManager.AddProperty(WIA_IPA_BITS_PER_CHANNEL ,WIA_IPA_BITS_PER_CHANNEL_STR ,RN,lBitsPerChannel);
                }

                if(SUCCEEDED(hr))
                {
                    //
                    // According with the limited type of input image data we use in this sample
                    // we'll initialize this property for 24-bit color / 3 channels RGB image data.
                    // (see also above the initialization of WIA_IPA_CHANNELS_PER_PIXEL and WIA_IPA_BITS_PER_CHANNEL)
                    // A real solution may need however to consider more than just this single format:
                    //
                    BYTE bBitsPerChannel[] = { 8, 8, 8 };
                    hr = PropertyManager.AddProperty(WIA_IPA_RAW_BITS_PER_CHANNEL, WIA_IPA_RAW_BITS_PER_CHANNEL_STR, RN, &bBitsPerChannel[0], 3);
                }

                if(SUCCEEDED(hr))
                {
                    //
                    // WIA_IPS_PHOTOMETRIC_INTERP is needed for the Raw transfer format:
                    // (It shall have WIA_PROP_LIST (with single valid value) | WIA_PROP_RW
                    //
                    CBasicDynamicArray<LONG> lPhotometricInterpArray;
                    lPhotometricInterpArray.Append(WIA_PHOTO_WHITE_1);
                    hr = PropertyManager.AddProperty(WIA_IPS_PHOTOMETRIC_INTERP, WIA_IPS_PHOTOMETRIC_INTERP_STR, RWL,
                        lPhotometricInterpArray[0], lPhotometricInterpArray[0], &lPhotometricInterpArray);
                }

                if(SUCCEEDED(hr))
                {
                    LONG lPlanar = WIA_PACKED_PIXEL;
                    hr = PropertyManager.AddProperty(WIA_IPA_PLANAR ,WIA_IPA_PLANAR_STR ,RN,lPlanar);
                }

                if(SUCCEEDED(hr))
                {
                    // TBD: A small buffer size was used here to allow slower transfers with more progress.  Real
                    //      drivers should use a higher value to increase performance.
                    LONG lBufferSize = DEFAULT_BUFFER_SIZE;
                    hr = PropertyManager.AddProperty(WIA_IPA_BUFFER_SIZE ,WIA_IPA_BUFFER_SIZE_STR ,RN,lBufferSize);
                }

                if(SUCCEEDED(hr))
                {
                    BSTR bstrFileExtension = SysAllocString(L"BMP");
                    if(bstrFileExtension)
                    {
                        hr = PropertyManager.AddProperty(WIA_IPA_FILENAME_EXTENSION ,WIA_IPA_FILENAME_EXTENSION_STR ,RN,bstrFileExtension);

                        SysFreeString(bstrFileExtension);
                        bstrFileExtension = NULL;
                    }
                    else
                    {
                        hr = E_OUTOFMEMORY;
                        WIAS_ERROR((g_hInst, "Could not allocate the file name extension property value, hr = 0x%lx.",hr));
                    }
                }

                /* Optional property
                if(SUCCEEDED(hr))
                {
                GUID guidStreamCompatID = GUID_NULL;
                hr = PropertyManager.AddProperty(WIA_IPA_PROP_STREAM_COMPAT_ID,WIA_IPA_PROP_STREAM_COMPAT_ID_STR,RN,guidStreamCompatID);
                }*/

                if(SUCCEEDED(hr))
                {
                    hr = PropertyManager.SetItemProperties(pWiasContext);
                    if(FAILED(hr))
                    {
                        WIAS_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA flatbed item properties, hr = 0x%lx",hr));
                    }
                }
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to obtain valid information from flatbed bitmap file resource to build a WIA property set"));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to obtain driver item context data"));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function initializes child item properties
 * needed for this WIA driver's storage item.  The
 * WIA_DRIVER_ITEM_CONTEXT structure stored as the
 * the WIA driver item context will be used to
 * properly set the WIA_IPA_FILENAME_EXTENSION property
 * value.
 *
 * @param pWiasContext
 *                  Pointer to the WIA item context
 * @param bRootItem TRUE - Legacy WIA properties that belong on the root item
 *                  of the device will be added.
 *                  FALSE - Child item WIA properties will be added to the item.
 * @param bFolderItem
 *                  TRUE - storage folder (WIA_CATEGORY_FOLDER)
 *                  FALSE - finished file (WIA_CATEGORY_FINISHED_FILE)
 * @return
 */
HRESULT InitializeWIAStorageItemProperties(
    _In_    BYTE        *pWiasContext,
            BOOL        bRootItem,
            BOOL        bFolderItem)
{
    UNREFERENCED_PARAMETER(bRootItem);

    HRESULT hr = E_INVALIDARG;
    if(pWiasContext)
    {
        CWIAPropertyManager PropertyManager;
        LONG                lItemType = 0;
        hr = wiasGetItemType(pWiasContext,&lItemType);
        if(SUCCEEDED(hr))
        {
            GUID guidItemCategory = bFolderItem ? WIA_CATEGORY_FOLDER : WIA_CATEGORY_FINISHED_FILE;
            hr = PropertyManager.AddProperty(WIA_IPA_ITEM_CATEGORY,WIA_IPA_ITEM_CATEGORY_STR,RN,guidItemCategory);
            if(SUCCEEDED(hr))
            {
                if(!(lItemType & WiaItemTypeGenerated))
                {
                    WIA_DRIVER_ITEM_CONTEXT *pWiaDriverItemContext = NULL;
                    hr = wiasGetDriverItemPrivateContext(pWiasContext,(BYTE**)&pWiaDriverItemContext);
                    if(SUCCEEDED(hr))
                    {
                        if(lItemType & WiaItemTypeStorage)
                        {
                            //
                            // This is the parent storage item, update the number of items stored and
                            // proper access rights
                            //

                            LONG lAccessRights = WIA_ITEM_READ;
                            hr = PropertyManager.AddProperty(WIA_IPA_ACCESS_RIGHTS ,WIA_IPA_ACCESS_RIGHTS_STR ,RF, lAccessRights, lAccessRights);
                            if(SUCCEEDED(hr))
                            {
                                hr = PropertyManager.AddProperty(WIA_IPA_ITEMS_STORED,
                                                             WIA_IPA_ITEMS_STORED_STR,
                                                             RN,
                                                             pWiaDriverItemContext->lNumItemsStored);
                                if(FAILED(hr))
                                {
                                    WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ITEMS_STORED property to the property manager, hr = 0x%lx",hr));
                                }
                            }
                            else
                            {
                                WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ACCESS_RIGHTS property to the property manager, hr = 0x%lx",hr));
                            }

                            //
                            // Support creation of child items underneath the root storage item:
                            //

                            BOOL bChildItemCreation = TRUE;
                            hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION_STR, RN, bChildItemCreation);
                            if(FAILED(hr))
                            {
                                WIAS_ERROR((g_hInst, "Failed to add WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION(TRUE) property to the property manager, hr = 0x%lx",hr));
                            }
                        }
                        else
                        {
                            //
                            // This must be a child item of some kind
                            //

                            if (SUCCEEDED(hr))
                            {
                                // Let enable delete for this item for better WIA testing
                                LONG lAccessRights = WIA_ITEM_READ | WIA_ITEM_CAN_BE_DELETED;
                                hr = PropertyManager.AddProperty(WIA_IPA_ACCESS_RIGHTS ,WIA_IPA_ACCESS_RIGHTS_STR ,RF, lAccessRights, lAccessRights);
                            }

                            if(SUCCEEDED(hr))
                            {
                                LONG lItemSize = 0;
                                hr = PropertyManager.AddProperty(WIA_IPA_ITEM_SIZE ,WIA_IPA_ITEM_SIZE_STR ,RN,lItemSize);
                            }

                            if(SUCCEEDED(hr))
                            {
                                GUID guidPreferredFormat = WiaImgFmt_UNDEFINED;
                                hr = PropertyManager.AddProperty(WIA_IPA_PREFERRED_FORMAT ,WIA_IPA_PREFERRED_FORMAT_STR ,RN,guidPreferredFormat);
                            }

                            if(SUCCEEDED(hr))
                            {
                                CBasicDynamicArray<GUID> guidFormatArray;
                                guidFormatArray.Append(WiaImgFmt_UNDEFINED);
                                hr = PropertyManager.AddProperty(WIA_IPA_FORMAT ,WIA_IPA_FORMAT_STR ,RWL,guidFormatArray[0],guidFormatArray[0],&guidFormatArray);
                            }

                            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(SUCCEEDED(hr))
                            {
                                // TBD: A small buffer size was used here to allow slower transfers with more progress.  Real
                                //      drivers should use a higher value to increase performance.
                                LONG lBufferSize = DEFAULT_BUFFER_SIZE;
                                hr = PropertyManager.AddProperty(WIA_IPA_BUFFER_SIZE ,WIA_IPA_BUFFER_SIZE_STR ,RN,lBufferSize);
                            }

                            if(SUCCEEDED(hr))
                            {
                                BSTR bstrFileExtension = NULL;
                                if(pWiaDriverItemContext->bstrStorageDataPath)
                                {
                                    hr = GetFileExtensionFromPath(pWiaDriverItemContext->bstrStorageDataPath, &bstrFileExtension);
                                }
                                else
                                {
                                    bstrFileExtension = SysAllocString(L"UNDEFINED");
                                    hr = S_OK;
                                }
                                if(SUCCEEDED(hr))
                                {
                                    if(bstrFileExtension)
                                    {
                                        hr = PropertyManager.AddProperty(WIA_IPA_FILENAME_EXTENSION ,WIA_IPA_FILENAME_EXTENSION_STR ,RN,bstrFileExtension);
                                        SysFreeString(bstrFileExtension);
                                        bstrFileExtension = NULL;
                                    }
                                    else
                                    {
                                        hr = E_OUTOFMEMORY;
                                        WIAS_ERROR((g_hInst, "Could not allocate the file name extension property value, hr = 0x%lx.",hr));
                                    }
                                }
                                else
                                {
                                    WIAS_ERROR((g_hInst, "Failed to extract file extension from path (%ws), hr = 0x%lx",pWiaDriverItemContext->bstrStorageDataPath,hr));
                                }
                            }

                            if (SUCCEEDED(hr))
                            {
                                //
                                // Support creation of child items underneath folder items:
                                //

                                if (bFolderItem)
                                {
                                    BOOL bChildItemCreation = TRUE;
                                    hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION_STR, RN, bChildItemCreation);
                                    if(FAILED(hr))
                                    {
                                        WIAS_ERROR((g_hInst, "Failed to add WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION property to the property manager, hr = 0x%lx",hr));
                                    }
                                }
                                else
                                {
                                    //
                                    // This is a child item (image item). So we add some image only properties here.
                                    //
                                    // This sample driver supports only 24-bpp color data. A real driver would have to consider separate WIA_IPA_DEPTH
                                    // values for each supported WIA_IPA_DATATYPE and update the available and current WIA_IPA_DEPTH values
                                    // every time the current WIA_IPA_DATATYPE is changed.
                                    //

                                    CBasicDynamicArray<LONG> lDataTypeArray;
                                    lDataTypeArray.Append(WIA_DATA_COLOR);
                                    hr = PropertyManager.AddProperty(WIA_IPA_DATATYPE ,WIA_IPA_DATATYPE_STR ,RWL,lDataTypeArray[0],lDataTypeArray[0],&lDataTypeArray);
                                    if(FAILED(hr))
                                    {
                                        WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_DATATYPE property to the property manager, hr = 0x%lx",hr));
                                    }

                                    CBasicDynamicArray<LONG> lBitDepthArray;
                                    lBitDepthArray.Append(24);
                                    hr = PropertyManager.AddProperty(WIA_IPA_DEPTH ,WIA_IPA_DEPTH_STR ,RWLC,lBitDepthArray[0],lBitDepthArray[0],&lBitDepthArray);
                                    if(FAILED(hr))
                                    {
                                        WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_DEPTH property to the property manager, hr = 0x%lx",hr));
                                    }
                                }

                            }
                        }
                    }
                    else
                    {
                        WIAS_ERROR((g_hInst, "Failed to obtain the WIA_DRIVER_ITEM_CONTEXT structure from the WIA driver item, hr = 0x%lx",hr));
                    }
                }
                else
                {
                    WIAS_TRACE((g_hInst,"WIA item was created by application"));

                    //
                    // Support creation of child items underneath generated folder items:
                    //
                    if (bFolderItem)
                    {
                        BOOL bChildItemCreation = TRUE;
                        hr = PropertyManager.AddProperty(WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION, WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION_STR, RN, bChildItemCreation);
                        if(FAILED(hr))
                        {
                            WIAS_ERROR((g_hInst, "Failed to add WIA_IPS_SUPPORTS_CHILD_ITEM_CREATION property to the property manager, hr = 0x%lx",hr));
                        }
                    }
                }
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to add WIA_IPA_ITEM_CATEGORY property to the property manager, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get the WIA item type, hr = 0x%lx",hr));
        }

        if(SUCCEEDED(hr))
        {
            hr = PropertyManager.SetItemProperties(pWiasContext);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "CWIAPropertyManager::SetItemProperties failed to set WIA storage item properties, hr = 0x%lx",hr));
            }
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function returns the WIA driver item context
 * data stored with the driver item.  NOT ALL DRIVER ITEMS
 * HAVE CONTEXTS STORED WITH THEM.  The context is initialized
 * and stored at WIA item creation.  See CreateWIAChildItem
 * function.
 *
 * @param pWiasContext
 *               Pointer to the WIA item context
 * @param ppWiaDriverItemContext
 *               Pointer to the WIA driver item context data
 * @return
 */
HRESULT wiasGetDriverItemPrivateContext(
    _In_    BYTE    *pWiasContext,
    _Out_   BYTE    **ppWiaDriverItemContext)
{
    HRESULT hr = E_INVALIDARG;
    if((pWiasContext)&&(ppWiaDriverItemContext))
    {
        IWiaDrvItem *pIWiaDrvItem   = NULL;
        hr = wiasGetDrvItem(pWiasContext, &pIWiaDrvItem);
        if(SUCCEEDED(hr))
        {
            hr = pIWiaDrvItem->GetDeviceSpecContext(ppWiaDriverItemContext);
            //
            // The caller will handle the failure case.  A failure, may mean that the
            // the WIA item does not have a private device specific context
            // stored.  This is OK, because is is not required.
            //
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get the WIA driver item from the application item, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function returns the application item's
 * parent WIA item context.  The returned context
 * can be used to access the parent's WIA property
 * set.
 *
 * @param pWiasContext
 *               Pointer to the WIA item context
 * @param ppWiasContext
 *               Pointer to the parent WIA item context
 * @return
 */
HRESULT wiasGetAppItemParent(
    _In_    BYTE    *pWiasContext,
    _Out_   BYTE    **ppWiasContext)
{
    HRESULT hr = E_INVALIDARG;
    if((pWiasContext) && (ppWiasContext))
    {
        // FIX! This helper function is actually getting the backing driver
        //      item and returning it as the parent.  This will make the
        //      driver always associate the newly created child item with its
        //      proper backing driver item.  This function should be fixed to
        //      return the parent application item.
        //

        IWiaDrvItem *pIWiaDrvItemParent = NULL;
        hr = wiasGetDrvItem(pWiasContext,&pIWiaDrvItemParent);
        if(SUCCEEDED(hr))
        {
            BSTR bstrFullItemName = NULL;
            hr = pIWiaDrvItemParent->GetFullItemName(&bstrFullItemName);
            if(SUCCEEDED(hr))
            {
                hr = wiasGetContextFromName(pWiasContext,0,bstrFullItemName,ppWiasContext);
                if(FAILED(hr))
                {
                    WIAS_ERROR((g_hInst, "Failed to get the parent's application item from the item name (%ws), hr = 0x%lx",bstrFullItemName,hr));
                }
                SysFreeString(bstrFullItemName);
                bstrFullItemName = NULL;
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to get full item name from parent IWiaDrvItem, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get the WIA driver item from the application item, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function converts a unit (in pixels) to
 * another unit (1/1000ths of an inch).
 *
 * @param lPixelLength
 *               Unit length in pixels
 * @param lResolution
 *               Resolution of Pixel unit length (in Dots Per Inch "DPI")
 * @return
 */
LONG ConvertTo1000thsOfAnInch(
    LONG lPixelLength,
    LONG lResolution)
{
    LONG lConvertedValue = 0;
    if((lPixelLength)&&(lResolution))
    {
        lConvertedValue = (LONG)((((lPixelLength * 1000) + lResolution - 1) / lResolution));
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return lConvertedValue;
}

/**
 * This function populates a BITMAPINFOHEADER structure
 * using data contained in a Gdiplus::BitmapData object.
 * This function only works with 24-bit data.
 *
 * @param pGDIPlusBitmapData
 *               Pointer to a GDI+ BitmapData object
 * @param pBitmapInfoHeader
 *               Pointer to a BITMAPINFOHEADER structure
 * @return
 */
HRESULT GetBitmapHeaderFromBitmapData(
    _In_    Gdiplus::BitmapData     *pGDIPlusBitmapData,
    _Out_   BITMAPINFOHEADER        *pBitmapInfoHeader)
{
    HRESULT hr = E_INVALIDARG;
    if((pGDIPlusBitmapData) && (pBitmapInfoHeader) && (pGDIPlusBitmapData->PixelFormat == PixelFormat24bppRGB))
    {
        memset(pBitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
        pBitmapInfoHeader->biSize       = sizeof(BITMAPINFOHEADER);
        pBitmapInfoHeader->biPlanes     = 1;
        pBitmapInfoHeader->biWidth      = pGDIPlusBitmapData->Width;
        pBitmapInfoHeader->biHeight     = pGDIPlusBitmapData->Height;

        // We cannot use the stride to calculate the size, because if there is no
        // format conversion, we might get the original bits...
        // We need to calculate the size based on the width
        pBitmapInfoHeader->biSizeImage  = ((((pGDIPlusBitmapData->Width * 3) + 3) & ~3) * pGDIPlusBitmapData->Height);

        pBitmapInfoHeader->biBitCount   = 24;
        hr = S_OK;
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function returns a Gdiplus::Rect structure
 * initialized with the current WIA extent setting
 * values.  This function assumes that the WIA item
 * passed in supports WIA_IPS_XPOS, WIA_IPS_YPOS,
 * WIA_IPS_XEXTENT and WIA_IPS_YEXTENT properties.
 *
 * @param pWiasContext
 *               Pointer to the WIA item context
 * @param pRect  Pointer to a Gdiplus::Rect object
 * @return
 */
HRESULT GetSelectionAreaRect(
    _In_    BYTE*           pWiasContext,
    _Out_   Gdiplus::Rect   *pRect)
{
    HRESULT hr = E_INVALIDARG;
    LONG    lXPos       = 0;
    LONG    lYPos       = 0;
    LONG    lXExtent    = 0;
    LONG    lYExtent    = 0;

    if((pWiasContext)&&(pRect))
    {
        hr = wiasReadPropLong(pWiasContext,WIA_IPS_XPOS,&lXPos,NULL,TRUE);
        if(SUCCEEDED(hr))
        {
            hr = wiasReadPropLong(pWiasContext,WIA_IPS_YPOS,&lYPos,NULL,TRUE);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "Failed to read the WIA_IPS_YPOS property, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to read the WIA_IPS_XPOS property, hr = 0x%lx",hr));
        }
        if(SUCCEEDED(hr))
        {
            hr = wiasReadPropLong(pWiasContext,WIA_IPS_YEXTENT,&lYExtent,NULL,TRUE);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "Failed to read the WIA_IPS_YEXTENT property, hr = 0x%lx",hr));
            }
        }
        if(SUCCEEDED(hr))
        {
            hr = wiasReadPropLong(pWiasContext,WIA_IPS_XEXTENT,&lXExtent,NULL,TRUE);
            if(FAILED(hr))
            {
                WIAS_ERROR((g_hInst, "Failed to read the WIA_IPS_XEXTENT property, hr = 0x%lx",hr));
            }
        }
        if(SUCCEEDED(hr))
        {
            Gdiplus::Rect rFrame((INT)lXPos,(INT)lYPos,(INT)lXExtent,(INT)lYExtent);
            *pRect = rFrame;
            hr = S_OK;
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function locks down a portion of a bitmap using
 * the current WIA extent setting values.  This function assumes that the WIA item
 * passed in supports WIA_IPS_XPOS, WIA_IPS_YPOS,
 * WIA_IPS_XEXTENT and WIA_IPS_YEXTENT properties.
 *
 * @param pWiasContext
 *                Pointer to the WIA item context
 * @param pBitmap Pointer to a Gdiplus::Bitmap object containing the
 *                bitmap data.
 * @param pBitmapData
 *                Pointer to a Gdiplus::BitmapData object
 * @param pbmih  Pointer to a BITMAPINFOHEADER structure that will
 *               receive the information about the locked area of the
 *               bitmap.
 * @param ppBitmapBits
 *                Pointer to the first scan line of data of the locked
 *                portion of the bitmap
 * @return
 */
HRESULT LockSelectionAreaOnBitmap(
    _In_    BYTE                    *pWiasContext,
    _In_    Gdiplus::Bitmap         *pBitmap,
    _Out_   Gdiplus::BitmapData     *pBitmapData,
    _In_    BITMAPINFOHEADER        *pbmih,
    _Outptr_result_maybenull_
            BYTE                    **ppBitmapBits)
{
    HRESULT hr = E_INVALIDARG;

    if((pBitmapData)&&(pbmih)&&(ppBitmapBits))
    {
        Gdiplus::Rect rFrame(0,0,0,0);
        hr = GetSelectionAreaRect(pWiasContext,&rFrame);

        if(SUCCEEDED(hr))
        {
            if(pBitmap->LockBits(&rFrame,
                                 ImageLockModeRead,
                                 PixelFormat24bppRGB,
                                 pBitmapData) == Ok)
            {
                hr = GetBitmapHeaderFromBitmapData(pBitmapData,pbmih);
                if(SUCCEEDED(hr))
                {
                    *ppBitmapBits = (BYTE*)pBitmapData->Scan0;
                }
                else
                {
                    WIAS_ERROR((g_hInst, "Failed to get the BITMAPINFOHEADER information from the GDI+ bitmap data object, hr = 0x%lx",hr));
                }
            }
            else
            {
                hr = E_FAIL;
                WIAS_ERROR((g_hInst, "Failed to LockBits on GDI+ bitmap object, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get selection area rect from WIA extent settings properties, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return  hr;
}

/**
 * This function unlocks a portion of a bitmap previously locked
 * by LockSelectionAreaOnBitmap function.
 *
 * @param pBitmap Pointer to a Gdiplus::Bitmap object containing the
 *                bitmap data.
 * @param pBitmapData
 *                Pointer to a Gdiplus::BitmapData object
 */
void UnlockSelectionAreaOnBitmap(
    _In_    Gdiplus::Bitmap         *pBitmap,
    _In_    Gdiplus::BitmapData     *pBitmapData)
{
    if((pBitmap)&&(pBitmapData))
    {
        if(pBitmap->UnlockBits(pBitmapData) != Ok)
        {
            WIAS_ERROR((g_hInst, "Failed to UnlockBits on GDI+ bitmap object"));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
}

/**
 * This helper function attempts to grab a IWiaMiniDrvTransferCallback interface
 * from a PMINIDRV_TRANSFER_CONTEXT structure.
 *
 * If successful, caller must Release.
 *
 * @param pmdtc  The PMINIDRV_TRANSFER_CONTEXT handed in during drvAcquireItemData.
 * @param ppIWiaMiniDrvTransferCallback
 *               Address of a interface pointer which receives the callback.
 * @return HRESULT return value.
 */
HRESULT GetTransferCallback(
    _In_        PMINIDRV_TRANSFER_CONTEXT       pmdtc,
    __callback  IWiaMiniDrvTransferCallback     **ppIWiaMiniDrvTransferCallback)
{
    HRESULT hr = E_INVALIDARG;
    if (pmdtc && ppIWiaMiniDrvTransferCallback)
    {
        if (pmdtc->pIWiaMiniDrvCallBack)
        {
            hr = pmdtc->pIWiaMiniDrvCallBack->QueryInterface(IID_IWiaMiniDrvTransferCallback,
                                                             (void**) ppIWiaMiniDrvTransferCallback);
        }
        else
        {
            hr = E_UNEXPECTED;
            WIAS_ERROR((g_hInst, "A NULL pIWiaMiniDrvCallBack was passed in the MINIDRV_TRANSFER_CONTEXT structure, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function allocates a buffer to be used during
 * data transfers.  FreeTransferBuffer should be called
 * to free the memory allocated by this function.
 *
 * @param pWiasContext
 *                 Pointer to the WIA item context
 * @param ppBuffer Pointer to the allocated buffer.  The caller should call
 *                 FreeTransferBuffer() when finished with this buffer.
 * @param pulBufferSize
 *                 Size of the buffer allocated.
 * @return
 */
HRESULT AllocateTransferBuffer(
    _In_    BYTE                    *pWiasContext,
    _Out_   BYTE                    **ppBuffer,
    _In_    ULONG                   *pulBufferSize)
{
    HRESULT hr = S_OK;

    if (pWiasContext && ppBuffer && pulBufferSize)
    {
        //
        // Set the buffer size to DEFAULT_BUFFER_SIZE
        //
        *pulBufferSize  = DEFAULT_BUFFER_SIZE;

        // Allocate the memory
        *ppBuffer = (BYTE*) CoTaskMemAlloc(*pulBufferSize);
        if (*ppBuffer)
        {
            hr = S_OK;
        }
        else
        {
            hr = E_OUTOFMEMORY;
            WIAS_ERROR((g_hInst, "Failed to allocate memory for transfer buffer, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
        hr = E_INVALIDARG;
    }
    return hr;
}

/**
 * This function frees any memory allocated using AllocateTransferBuffer()
 * function.
 *
 * @param pBuffer Pointer to a buffer allocated with the AllocateTransferBuffer()
 *                function.
 */
void FreeTransferBuffer(
    _In_    BYTE                    *pBuffer)
{
    // Free the memory
    if (pBuffer)
    {
        CoTaskMemFree(pBuffer);
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed. (Attempted to free NULL transfer buffer)"));
    }
}

/**
 * This function attempts to extract the file
 * extension from a file path.  It is assumed that
 * the passed in path contains an extension of some
 * type. (e.g. x:\xxxxx\xxx\xxxxxx.xxx)
 *
 * @param bstrFullPath
 *               Full path containing extension
 * @param pbstrExtension
 *               Extracted extension
 * @return
 */
HRESULT GetFileExtensionFromPath(
    _In_    BSTR    bstrFullPath,
    _Out_   BSTR    *pbstrExtension)
{
    HRESULT hr = E_INVALIDARG;
    if((bstrFullPath)&&(pbstrExtension))
    {
        CBasicStringWide cswPath = bstrFullPath;
        CBasicStringWide cswExtension;
        if(cswPath.Length())
        {
            size_t iEndIndex   = cswPath.Length();
            size_t iStartIndex = cswPath.ReverseFind(TEXT("."));
            if(iStartIndex > 0)
            {
                cswExtension = cswPath.SubStr((iStartIndex + 1),iEndIndex);
                cswExtension = cswExtension.ToUpper();
            }
        }
        *pbstrExtension = SysAllocString(cswExtension.String());
        if(*pbstrExtension)
        {
            hr = S_OK;
        }
        else
        {
            hr = E_OUTOFMEMORY;
            WIAS_ERROR((g_hInst, "Failed to allocate memory for BSTR file extension string, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Invalid parameters were passed"));
    }
    return hr;
}

/**
 * This function returns TRUE is the WIA item passed
 * in contains the WIA item flag setting of
 * WiaItemTypeProgrammableDataSource.
 *
 * @param pWiasContext
 *                 Pointer to the WIA item context
 * @return
 */
bool IsProgrammableItem(
    _In_    BYTE    *pWiasContext)
{
    LONG    lItemType   = 0;
    HRESULT hr          = S_OK;
    hr = wiasGetItemType(pWiasContext,&lItemType);
    return ((lItemType & WiaItemTypeProgrammableDataSource) == WiaItemTypeProgrammableDataSource);
}

/**
 * This function queues a WIA event using the passed in
 * WIA item context.
 *
 * @param pWiasContext
 *               Pointer to the WIA item context
 * @param guidWIAEvent
 *               WIA event to queue
 */
void QueueWIAEvent(
    _In_    BYTE        *pWiasContext,
            const GUID  &guidWIAEvent)
{
    HRESULT hr                  = S_OK;
    BSTR    bstrDeviceID        = NULL;
    BSTR    bstrFullItemName    = NULL;
    BYTE    *pRootItemContext   = NULL;

    hr = wiasReadPropStr(pWiasContext, WIA_IPA_FULL_ITEM_NAME, &bstrFullItemName, NULL,TRUE);
    if(SUCCEEDED(hr))
    {
        hr = wiasGetRootItem(pWiasContext,&pRootItemContext);
        if(SUCCEEDED(hr))
        {
            hr = wiasReadPropStr(pRootItemContext, WIA_DIP_DEV_ID,&bstrDeviceID, NULL,TRUE);
            if(SUCCEEDED(hr))
            {
                hr = wiasQueueEvent(bstrDeviceID,&guidWIAEvent,bstrFullItemName);
                if(FAILED(hr))
                {
                    WIAS_ERROR((g_hInst, "Failed to queue WIA event, hr = 0x%lx",hr));
                }
            }
            else
            {
                WIAS_ERROR((g_hInst, "Failed to read the WIA_DIP_DEV_ID property, hr = 0x%lx",hr));
            }
        }
        else
        {
            WIAS_ERROR((g_hInst, "Failed to get the Root item from child item, using wiasGetRootItem, hr = 0x%lx",hr));
        }
    }
    else
    {
        WIAS_ERROR((g_hInst, "Failed to read WIA_IPA_FULL_ITEM_NAME property, hr = %lx",hr));
    }

    if(bstrFullItemName)
    {
        SysFreeString(bstrFullItemName);
        bstrFullItemName = NULL;
    }

    if(bstrDeviceID)
    {
        SysFreeString(bstrDeviceID);
        bstrDeviceID = NULL;
    }
}

Our Services

  • What our customers say about us?

© 2011-2024 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS