/*************************************************************************** * * (C) COPYRIGHT MICROSOFT CORP., 1999 * * TITLE: MiniDrv.Cpp * * VERSION: 3.0 * * DATE: 18 Nov, 1999 * * DESCRIPTION: * Implementation of the WIA test scanner methods. * ****************************************************************************/ #include #include #include #include #include #include "resource.h" #include "testusd.h" #include "defprop.h" // // Defines for scan phase. Used in data transfers // #define START 0 #define CONTINUE 1 #define END 2 // // Handle to the module used for WIAS_ERROR and WIAS_TRACE // extern HINSTANCE g_hInst; // // Pointer to WIA Logging Interface used for WIAS_LERROR and WIAS_LTRACE // extern IWiaLog *g_pIWiaLog; // // Prototypes for private functions implemented in MiniDrv.Cpp // HRESULT _stdcall GetBmiSize(PBITMAPINFO pbmi, LONG *plBmiSize); UINT AlignInPlace( PBYTE pBuffer, LONG cbWritten, LONG lBytesPerScanLine, LONG lBytesPerScanLineRaw); /**************************************************************************\ * ValidateDataTransferContext * * Checks the data transfer context to ensure it's valid. * * Arguments: * * pDataTransferContext - Pointer the data transfer context. * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT ValidateDataTransferContext( PMINIDRV_TRANSFER_CONTEXT pDataTransferContext) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "::ValidateDataTransferContext"); if (pDataTransferContext->lSize != sizeof(MINIDRV_TRANSFER_CONTEXT)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ValidateDataTransferContext, invalid data transfer context")); return E_INVALIDARG;; } // // for tymed file, only WiaImgFmt_BMP is allowed by this driver // if (pDataTransferContext->tymed == TYMED_FILE) { if (pDataTransferContext->guidFormatID != WiaImgFmt_BMP) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireDeviceData, invalid format")); return E_INVALIDARG;; } } // // for tymed CALLBACK, only WiaImgFmt_MEMORYBMP is allowed by this driver // if (pDataTransferContext->tymed == TYMED_CALLBACK) { if (pDataTransferContext->guidFormatID != WiaImgFmt_MEMORYBMP) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireDeviceData, invalid format")); return E_INVALIDARG;; } } // // callback is always double buffered, non-callback never is // if (pDataTransferContext->pTransferBuffer == NULL) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("AcquireDeviceData, invalid transfer buffer")); return E_INVALIDARG; } return S_OK; } /**************************************************************************\ * TestUsdDevice::drvDeleteItem * * Try to delete a device item. Device items for the test scanner may * not be modified, so simply return access denied. * * Arguments: * * pWiasContext - Indicates the item to delete. * lFlags - Operation flags, unused. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvDeleteItem( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { plDevErrVal = 0; CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvDeleteItem"); return STG_E_ACCESSDENIED; } /**************************************************************************\ * SendBitmapHeader * * Send the bitmap header info to the callback routine. This is a helper * function used in TYMED_CALLBACK transfers. * * Arguments: * * pmdtc - a pointer to a transfer context. * * Return Value: * * Status * * History: * * 11/17/1998 Original Version * \**************************************************************************/ HRESULT SendBitmapHeader( PMINIDRV_TRANSFER_CONTEXT pmdtc) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "::SendBitmapHeader"); HRESULT hr; WIAS_ASSERT( g_hInst, pmdtc != NULL); WIAS_ASSERT( g_hInst, pmdtc->tymed == TYMED_CALLBACK); WIAS_ASSERT( g_hInst, pmdtc->guidFormatID == WiaImgFmt_MEMORYBMP); // // Driver is sending TOPDOWN data, must swap biHeight // // This routine assumes pMiniTranCtx->pHeader points to a // BITMAPINFO header (TYMED_FILE doesn't use this path // and DIB is the only format supported). // PBITMAPINFO pbmi = (PBITMAPINFO)pmdtc->pTransferBuffer; pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight; // // Send to class driver. WIA Class driver will pass // data through to client. // hr = pmdtc-> pIWiaMiniDrvCallBack-> MiniDrvCallback(IT_MSG_DATA, IT_STATUS_TRANSFER_TO_CLIENT, 0, 0, pmdtc->lHeaderSize, pmdtc, 0); if (hr == S_OK) { // // If the transfer was successfull, advance offset for // destination copy by the size of the data just sent. // pmdtc->cbOffset += pmdtc->lHeaderSize; } return hr; } /**************************************************************************\ * ScanItem * * Copy data from scanner into buffer. This routine must fill the * complete buffer. Status is sent back to the client if a callback * routine is provided. * * Data must be copied to the buffer from the bottom up to compensate * for WiaImgFmt_BMP that defines DIB data as "BOTTOM-UP" :( * * Arguments: * * pItemContext - private item data * pMiniTranCtx - mini dirver supplied transfer info * plDevErrVal - device error value * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::ScanItem( PTESTMINIDRIVERITEMCONTEXT pItemContext, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::ScanItem"); HRESULT hr = S_OK; // // Init buffer info // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("")); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("ScanItem:")); LONG cbWritten = 0; LONG cbSize; LONG cbRemaining = pmdtc->lBufferSize - pmdtc->lHeaderSize; PBYTE pBuf = pmdtc->pTransferBuffer + pmdtc->lHeaderSize; LONG lPhase = START; //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pmdtc->lBufferSize: %d", pmdtc->lBufferSize)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pmdtc->lHeaderSize: %d",pmdtc ->lHeaderSize)); if (pItemContext->lBytesPerScanLine == 0) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, lBytesPerScanLine == 0")); return E_FAIL; } // // Scan until buffer runs out or scanner completes transfer // while ((lPhase == START) || (cbWritten)) { //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbRemaining: %d", cbRemaining)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pItemContext->lBytesPerScanLine: %d", pItemContext->lBytesPerScanLine)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pItemContext->lBytesPerScanLineRaw: %d", pItemContext->lBytesPerScanLineRaw)); // // Limit requests to 64K or less. Capping requests is driver specific. // cbSize = (cbRemaining > 0x10000) ? 0x10000 : cbRemaining; // // Request size to scanner must be modula the raw bytes per scan row. // Enough space for the alignment padding must be reserved. // These are requirements for the helper AlignInPlace(). // cbSize = (cbSize / pItemContext->lBytesPerScanLine) * pItemContext->lBytesPerScanLineRaw; // // Check if the scan is finished. If cbSize == 0 then we've transfered // all the necessary data, so break from the scan loop. // if (cbSize == 0) { break; } //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lPhase: %d", lPhase)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pBuf: %08X", pBuf)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbSize: %d", cbSize)); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbRemaining: %d", cbRemaining)); // // Device specific call to get data from the scanner and put it into // a buffer. cbSize is the requested number of bytes to retrieve // from the scanner, and cbWritten will be set to the actual number // of bytes that were returned. // hr = Scan(pmdtc->guidFormatID, lPhase, pBuf, cbSize, &cbWritten, pItemContext, pmdtc); //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbWritten: %d", cbWritten)); // // Change scan phase from START to CONTINUE, so that next call to // Scan(...) will be in the correct phase. // if (lPhase == START) { lPhase = CONTINUE; } if (hr == S_OK) { if (cbWritten) { // // Align the data on DWORD boundries. // cbWritten = AlignInPlace(pBuf, cbWritten, pItemContext->lBytesPerScanLine, pItemContext->lBytesPerScanLineRaw); // // Advance the buffer // pBuf += cbWritten; cbRemaining -= cbWritten; // // If a status callback was specified, then callback the class // driver. // if (pmdtc->pIWiaMiniDrvCallBack) { // // Calculate the percent complete for status. // FLOAT FractionComplete; LONG PercentComplete; if (pmdtc->lBufferSize) { FractionComplete = (FLOAT)(pmdtc->lBufferSize - cbRemaining) / (FLOAT)pmdtc->lBufferSize; } else { FractionComplete = 0.0f; WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, pmdtc->lBufferSize = 0!")); } PercentComplete = (LONG)(100 * FractionComplete); // // Send status to class driver. WIA Class driver will // pass status to client. // hr = pmdtc-> pIWiaMiniDrvCallBack-> MiniDrvCallback(IT_MSG_STATUS, IT_STATUS_TRANSFER_TO_CLIENT, PercentComplete, 0, 0, pmdtc, 0); // // If user cancels scan, S_FALSE will be returned by // callback. Also check for error, and abort scan // if one occurred. // if (hr == S_FALSE) { WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("ScanItem, Transfer canceled by client")); break; } else if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, MiniDrvCallback failed")); WIAS_LHRESULT(g_pIWiaLog, hr); break; } } } } else { hr = E_FAIL; WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItem, data transfer failed")); GetLastError((PULONG)plDevErrVal); break; } } // // Let the scanner know we are done. // Scan(GUID_NULL, END, NULL, 0, NULL, pItemContext, pmdtc); return hr; } /**************************************************************************\ * ScanItemCB * * Use client data callbacks to transfer banded data into app transfer * buffer and callback client * * Arguments: * * pItemContext - private item data * pmdtc - buffer and callback information * plDevErrVal - device error value * * Return Value: * * Status * * History: * * 11/17/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::ScanItemCB( PTESTMINIDRIVERITEMCONTEXT pItemContext, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::ScanItemCB"); HRESULT hr = S_OK; WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("")); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("ScanItemCB:")); // // There must be a callback supplied, else fail the transfer. // if ((pmdtc->pIWiaMiniDrvCallBack == NULL) || (!pmdtc->bTransferDataCB)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, invalid callback params")); return E_INVALIDARG; } // // Send Bitmap header. // hr = SendBitmapHeader(pmdtc); // // Transfer may have failed or been canceled. Only continue if S_OK. // if (hr != S_OK) { return hr; } //WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("ScanItemCB, lBufferSize: 0x%lx\n", pmdtc->lBufferSize)); if (pItemContext->lBytesPerScanLine == 0) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, lBytesPerScanLine == 0")); return E_FAIL; } // // Init buffer variables // LONG cbWritten; LONG cbSize; LONG cbRemaining = pmdtc->lBufferSize; LONG lPhase = START; // // Scan until buffer runs out or scanner completes transfer // while ((lPhase == START) || (cbWritten)) { PBYTE pBuf = pmdtc->pTransferBuffer; // // Limit requests to 64K or less. Capping requests is driver // specific. The smaller the limit, the more frequent the // status messages. // cbSize = (cbRemaining > 0x10000) ? 0x10000 : cbRemaining; // // Request size to scanner must be modula the raw bytes per scan row. // Enough space for the alignment padding must be reserved. // These are requirements for the helper AlignInPlace(). // cbSize = (cbSize / pItemContext->lBytesPerScanLine) * pItemContext->lBytesPerScanLineRaw; // // Check if the scan is finished. If cbSize == 0 then we've transfered // all the necessary data, so break from the scan loop. // if (cbSize == 0) { break; } // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lPhase: %d", lPhase)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pBuf: %08X", pBuf)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbSize: %d", cbSize)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbRemaining: %d", cbRemaining)); // // Device specific call to get data from the scanner and put it into // a buffer. cbSize is the requested number of bytes to retrieve // from the scanner, and cbWritten will be set to the actual number // of bytes that were returned. // hr = Scan(pmdtc->guidFormatID, lPhase, pBuf, cbSize, &cbWritten, pItemContext, pmdtc); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" cbWritten: %d", cbWritten)); // // Change scan phase from START to CONTINUE, so that next call to // Scan(...) will be in the correct phase. // if (lPhase == START) { lPhase = CONTINUE; } if (hr == S_OK) { if (cbWritten) { // // Align the data on DWORD boundries. // cbWritten = AlignInPlace(pBuf, cbWritten, pItemContext->lBytesPerScanLine, pItemContext->lBytesPerScanLineRaw); // // Calculate the percent complete for status. // FLOAT FractionComplete; LONG PercentComplete; if ((pmdtc->lImageSize + pmdtc->lHeaderSize)) { FractionComplete = (FLOAT) (pmdtc->cbOffset + cbWritten) / (FLOAT) (pmdtc->lImageSize + pmdtc->lHeaderSize); } else { FractionComplete = 0.0f; WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, pmdtc->lImageSize + pmdtc->lHeaderSize= 0!")); } PercentComplete = (LONG)(100 * FractionComplete); // // Send data to class driver. WIA Class driver will // pass data to client. // hr = pmdtc-> pIWiaMiniDrvCallBack-> MiniDrvCallback(IT_MSG_DATA, IT_STATUS_TRANSFER_TO_CLIENT, PercentComplete, pmdtc->cbOffset, cbWritten, pmdtc, 0); // // If user cancels scan, S_FALSE will be returned by // callback. Also check for error, and abort scan // if one occurred. // if (hr == S_FALSE) { WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("ScanItemCB, MiniDrvCallback canceled by client")); break; } else if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, MiniDrvCallback failed")); WIAS_LHRESULT(g_pIWiaLog, hr); DebugBreak(); break; } pmdtc->cbOffset += cbWritten; } } else { hr = E_FAIL; WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("ScanItemCB, data transfer failed")); GetLastError((PULONG)plDevErrVal); break; } } // Let the hardware know we are done scanning. Scan(GUID_NULL, END, NULL, 0, NULL, pItemContext, pmdtc); return hr; } /**************************************************************************\ * TestUsdDevice::drvAcquireItemData * * Transfer data from mini driver item to device manger. * * Arguments: * * pWiasContext - Pointer to the WIA item. * lFlags - Operation flags, unused. * pmdtc - Pointer to mini driver context. On entry, only the * portion of the mini driver context which is derived * from the item properties is filled in. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 11/17/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvAcquireItemData( BYTE *pWiasContext, LONG lFlags, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvAcquireItemData"); HRESULT hr; plDevErrVal = 0; // // Get a pointer to the associated driver item. // IWiaDrvItem* pDrvItem; hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } // // Validate the data transfer context. // hr = ValidateDataTransferContext(pmdtc); if (FAILED(hr)) { return hr; } // // Get item specific driver data // PTESTMINIDRIVERITEMCONTEXT pItemContext; hr = pDrvItem->GetDeviceSpecContext((BYTE**)&pItemContext); if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, NULL item context")); return hr; } // // Set data source file name. This is where the test scanner // gets it's data from. // hr = SetSrcBmp((BYTE*)pWiasContext); if (hr != S_OK) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, SetSrcBmp failed")); return hr; } // // Use WIA services to fetch format specific info. This information // is based on the property settings. // hr = wiasGetImageInformation(pWiasContext, 0, pmdtc); if (hr != S_OK) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvAcquireItemData, GetImageInformation failed")); return hr; } // // Determine if this is a callback or buffered transfer. // if (pmdtc->tymed == TYMED_CALLBACK) { hr = ScanItemCB(pItemContext, pmdtc, plDevErrVal); } else { hr = ScanItem(pItemContext, pmdtc, plDevErrVal); } if (!pmdtc->bClassDrvAllocBuf) { CoTaskMemFree(pmdtc->pTransferBuffer); } return hr; } /**************************************************************************\ * SetItemSize * * Call wias to calc new item size * * Arguments: * * pWiasContext - item * * Return Value: * * Status * * History: * * 4/21/1999 Original Version * \**************************************************************************/ HRESULT SetItemSize( BYTE *pWiasContext) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "::SetItemSize"); #define NUM_PROPS_TO_SET 3 LONG lWidthInBytes = 0; LONG lMinBufSize = 0; PROPSPEC ps[NUM_PROPS_TO_SET] = { {PRSPEC_PROPID, WIA_IPA_ITEM_SIZE}, {PRSPEC_PROPID, WIA_IPA_BYTES_PER_LINE}, {PRSPEC_PROPID, WIA_IPA_MIN_BUFFER_SIZE}}; PROPVARIANT pv[NUM_PROPS_TO_SET]; HRESULT hr = S_OK; MINIDRV_TRANSFER_CONTEXT mdtc; // // Clear the MiniDrvTransferContext // memset(&mdtc,0,sizeof(MINIDRV_TRANSFER_CONTEXT)); // // Read format and tymed // GUID guidFormatID; hr = wiasReadPropGuid(pWiasContext, WIA_IPA_FORMAT, &guidFormatID, NULL, TRUE); if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadPropLong WIA_IPA_FORMAT error")); return hr; } hr = wiasReadPropLong(pWiasContext,WIA_IPA_TYMED, (LONG*)&mdtc.tymed, NULL, TRUE); if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, ReadPropLong WIA_IPA_TYMED error")); return hr; } // // wias works for DIB,TIFF formats // hr = wiasGetImageInformation(pWiasContext, WIAS_INIT_CONTEXT, &mdtc); if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, could not get image information")); return hr; } // // Set the MinBufferSize property. MinBufferSize is the minimum buffer // that a client can request for a data transfer. // switch (mdtc.tymed) { case TYMED_CALLBACK: lMinBufSize = 65535; break; case TYMED_FILE: lMinBufSize = mdtc.lImageSize + mdtc.lHeaderSize; break; default: WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, unknown tymed: 0x%08X", mdtc.tymed)); return E_INVALIDARG; } // // Initialize propvar's. Then write the values. Don't need to call // PropVariantClear when done, since there are only LONG values. // for (int i = 0; i < NUM_PROPS_TO_SET; i++) { PropVariantInit(&pv[i]); pv[i].vt = VT_I4; } pv[0].lVal = mdtc.lItemSize; pv[1].lVal = mdtc.cbWidthInBytes; pv[2].lVal = lMinBufSize; hr = wiasWriteMultiple(pWiasContext, NUM_PROPS_TO_SET, ps, pv); if (SUCCEEDED(hr)) { // // Get a pointer to the associated driver item. // IWiaDrvItem* pDrvItem; hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } PTESTMINIDRIVERITEMCONTEXT pItemContext; hr = pDrvItem->GetDeviceSpecContext((BYTE**)&pItemContext); if (SUCCEEDED(hr)) { // // Calculate how many scan lines will fit in the buffer. // pItemContext->lBytesPerScanLineRaw = ((mdtc.lWidthInPixels * mdtc.lDepth) + 7) / 8; pItemContext->lBytesPerScanLine = (((mdtc.lWidthInPixels * mdtc.lDepth) + 31) / 8) & 0xfffffffc; pItemContext->lTotalRequested = pItemContext->lBytesPerScanLineRaw * mdtc.lLines; } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvWriteItemProperties, NULL item context")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetItemSize, WriteMultiple failed")); } return hr; } /**************************************************************************\ * TestUsdDevice::drvInitItemProperties * * Initialize the device item properties. Called during item * initialization. This is called by the WIA Class driver * after the item tree has been built. It is called once for every * item in the tree. * * Arguments: * * pWiasContext - Pointer to WIA item. * lFlags - Operation flags, unused. * plDevErrVal - Pointer to the device error value. * * * Return Value: * * Status * * History: * * 10/29/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvInitItemProperties( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvInitItemProperties"); HRESULT hr = S_OK; // // This device doesn't touch hardware to initialize the device item // properties, so set plDevErrVal to 0. // *plDevErrVal = 0; // // Get a pointer to the associated driver item. // IWiaDrvItem* pDrvItem; hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } // // Set initial item properties. // LONG lItemType = 0; pDrvItem->GetItemFlags(&lItemType); if (lItemType & WiaItemTypeRoot) { // // This is for the root item. // // // Build Root Item Properties, initializing global // structures with their default and valid values // hr = BuildRootItemProperties(); if(FAILED(hr)) { return hr; } // // Add the device specific root item property names, // using WIA service. // hr = wiasSetItemPropNames(pWiasContext, NUM_ROOTITEMDEFAULTS, g_piRootItemDefaults, g_pszRootItemDefaults); if (FAILED(hr)) { return hr; } // // Set the device specific root item properties to // their default values using WIA service. // hr = wiasWriteMultiple(pWiasContext, NUM_ROOTITEMDEFAULTS, g_psRootItemDefaults, g_pvRootItemDefaults); // // Free PROPVARIANT array, This frees any memory that was allocated for a prop variant value. // FreePropVariantArray(NUM_ROOTITEMDEFAULTS,g_pvRootItemDefaults); if (FAILED(hr)) { return hr; } // // Use WIA services to set the property access and // valid value information from g_wpiItemDefaults. // hr = wiasSetItemPropAttribs(pWiasContext, NUM_ROOTITEMDEFAULTS, g_psRootItemDefaults, g_wpiRootItemDefaults); } else { // // This is for the child item.(Top) // // // Build Top Item Properties, initializing global // structures with their default and valid values // hr = BuildTopItemProperties(); if(FAILED(hr)) { return hr; } // // Use the WIA service to set the item property names. // hr = wiasSetItemPropNames(pWiasContext, NUM_ITEMDEFAULTS, g_piItemDefaults, g_pszItemDefaults); if (FAILED(hr)) { return hr; } // // Use WIA services to set the item properties to their default // values. // hr = wiasWriteMultiple(pWiasContext, NUM_ITEMDEFAULTS, g_psItemDefaults, (PROPVARIANT*)g_pvItemDefaults); if (FAILED(hr)) { return hr; } // // Use WIA services to set the property access and // valid value information from g_wpiItemDefaults. // hr = wiasSetItemPropAttribs(pWiasContext, NUM_ITEMDEFAULTS, g_psItemDefaults, g_wpiItemDefaults); if (FAILED(hr)) { return hr; } // // Set item size properties. // hr = SetItemSize(pWiasContext); } return hr; } /**************************************************************************\ * TestUsdDevice::drvValidateItemProperties * * Validate the device item properties. It is called when changes are made * to an item's properties. Driver should not only check that the values * are valid, but must update any valid values that may change as a result. * If an a property is not being written by the application, and it's value * is invalid, then "fold" it to a new value, else fail validation (because * the application is setting the property to an invalid value). * * Arguments: * * pWiasContext - Pointer to the WIA item, unused. * lFlags - Operation flags, unused. * nPropSpec - The number of properties that are being written * pPropSpec - An array of PropSpecs identifying the properties that * are being written. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/29/1998 Original Version ***************************************************************************/ HRESULT _stdcall TestUsdDevice::drvValidateItemProperties( BYTE *pWiasContext, LONG lFlags, ULONG nPropSpec, const PROPSPEC *pPropSpec, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvValidateItemProperties"); WIA_PROPERTY_CONTEXT Context; HRESULT hr = S_OK; LONG lItemType; // // This device doesn't touch hardware to validate the device item // properties, so set device error to 0. // *plDevErrVal = 0; hr = wiasGetItemType(pWiasContext, &lItemType); if (SUCCEEDED(hr)) { if (lItemType & WiaItemTypeRoot) { // // Insert root item validation here // } else { // // Validate the child item properties here. Start with // dependent property validation, followed by a general // property validation against their valid values with // wiasValidateItemProperties. // // // Create a property context needed by some WIA Service // functions used below. // hr = wiasCreatePropContext(nPropSpec, (PROPSPEC*)pPropSpec, 0, NULL, &Context); if (SUCCEEDED(hr)) { // // Check Current Intent first // hr = CheckIntent(pWiasContext, &Context); if (SUCCEEDED(hr)) { // // Check if DataType is being written // hr = CheckDataType(pWiasContext, &Context); if (SUCCEEDED(hr)) { // // Use the WIA service to update the scan rect // properties and valid values. // hr = wiasUpdateScanRect(pWiasContext, &Context, HORIZONTAL_BED_SIZE, VERTICAL_BED_SIZE); if (SUCCEEDED(hr)) { // // Use the WIA Service to update the valid values // for Format. These are based on the value of // WIA_IPA_TYMED, so validation is also performed // on the tymed property by the service. // hr = wiasUpdateValidFormat(pWiasContext, &Context, (IWiaMiniDrv*) this); if (SUCCEEDED(hr)) { // // Check Preferred format // hr = CheckPreferredFormat(pWiasContext, &Context); } } } } wiasFreePropContext(&Context); } // // Update the item size // if (SUCCEEDED(hr)) { hr = SetItemSize(pWiasContext); } // // If all necessary changes have been made // successfully, validate the properties against // their new valid values. // if (SUCCEEDED(hr)) { hr = wiasValidateItemProperties(pWiasContext, nPropSpec, pPropSpec); } } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvValidateItemProperties, could not get item type")); } return hr; } /**************************************************************************\ * TestUsdDevice::drvWriteItemProperties * * Write the device item properties to the hardware. This is called by the * WIA Class driver prior to drvAcquireItemData when the client requests * a data transfer. * * Arguments: * * pWiasContext - Pointer to WIA item. * lFlags - Operation flags, unused. * pmdtc - Pointer to mini driver context. On entry, only the * portion of the mini driver context which is derived * from the item properties is filled in. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/29/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvWriteItemProperties( BYTE *pWiasContext, LONG lFlags, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvWriteItemProperties"); HRESULT hr = S_OK; // No device hardware errors. *plDevErrVal = 0; // // The Test Scanner has no hardware, so there is nothing to do here. // return hr; } /**************************************************************************\ * TestUsdDevice::drvReadItemProperties * * Read the device item properties. When a client application tries to * read a WIA Item's properties, the WIA Class driver will first notify * the driver by calling this method. * * Arguments: * * pWiasContext - wia item * lFlags - Operation flags, unused. * nPropSpec - Number of elements in pPropSpec. * pPropSpec - Pointer to property specification, showing which properties * the application wants to read. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/29/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvReadItemProperties( BYTE *pWiasContext, LONG lFlags, ULONG nPropSpec, const PROPSPEC *pPropSpec, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvReadItemProperties"); // // For most scanner devices, item properties are stored in the driver // and written out at acquire image time. Some devices support properties // which should be updated on every property read e.g. say there was // a property representing the device's internal clock. // The updating of such properties should be done here. // *plDevErrVal = 0; return S_OK; } /**************************************************************************\ * TestUsdDevice::drvLockWiaDevice * * Lock access to the device. * * Arguments: * * pWiasContext - unused, can be NULL * lFlags - Operation flags, unused. * plDevErrVal - Pointer to the device error value. * * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvLockWiaDevice"); *plDevErrVal = 0; return m_pStiDevice->LockDevice(100); } /**************************************************************************\ * TestUsdDevice::drvUnLockWiaDevice * * Unlock access to the device. * * Arguments: * * pWiasContext - Pointer to the WIA item, unused. * lFlags - Operation flags, unused. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvUnLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvUnLockWiaDevice"); *plDevErrVal = 0; return m_pStiDevice->UnLockDevice(); } /**************************************************************************\ * TestUsdDevice::drvAnalyzeItem * * This scanner does not support image analysis, so return E_NOTIMPL. * * Arguments: * * pWiasContext - Pointer to the device item to be analyzed. * lFlags - Operation flags. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvAnalyzeItem( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvAnalyzeItem"); *plDevErrVal = 0; return E_NOTIMPL; } /**************************************************************************\ * TestUsdDevice::drvFreeDrvItemContext * * Free any device specific context. * * Arguments: * * lFlags - Operation flags, unused. * pDevSpecContext - Pointer to device specific context. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvFreeDrvItemContext( LONG lFlags, BYTE *pSpecContext, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvFreeDrvItemContext"); PTESTMINIDRIVERITEMCONTEXT pContext; *plDevErrVal = 0; pContext = (PTESTMINIDRIVERITEMCONTEXT) pSpecContext; if (pContext) { // Free any driver item specific context here. } return S_OK; } /**************************************************************************\ * TestUsdDevice::drvInitializeWia * * Initialize the WIA mini driver. This will build up the driver item tree * and perform any other initialization code that's needed for WIA. * * Arguments: * * pWiasContext - Pointer to the WIA item, unused. * lFlags - Operation flags, unused. * bstrDeviceID - Device ID. * bstrRootFullItemName - Full item name. * pIPropStg - Device info. properties. * pStiDevice - STI device interface. * pIUnknownOuter - Outer unknown interface. * ppIDrvItemRoot - Pointer to returned root item. * ppIUnknownInner - Pointer to returned inner unknown. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvInitializeWia( BYTE *pWiasContext, LONG lFlags, BSTR bstrDeviceID, BSTR bstrRootFullItemName, IUnknown *pStiDevice, IUnknown *pIUnknownOuter, IWiaDrvItem **ppIDrvItemRoot, IUnknown **ppIUnknownInner, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvInitializeWia"); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("drvInitializeWia, device ID: %ws", bstrDeviceID)); HRESULT hr = S_OK; *plDevErrVal = 0; *ppIDrvItemRoot = NULL; *ppIUnknownInner = NULL; // // Need to init names and STI pointer? // if (m_pStiDevice == NULL) { // // save STI device inteface for locking // m_pStiDevice = (IStiDevice *)pStiDevice; // // Cache the device ID. // m_bstrDeviceID = SysAllocString(bstrDeviceID); if (!m_bstrDeviceID) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate device ID string")); return E_OUTOFMEMORY; } // // Cache the root property stream name. // m_bstrRootFullItemName = SysAllocString(bstrRootFullItemName); if (!m_bstrRootFullItemName) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvInitializeWia, unable to allocate prop stream name")); return E_OUTOFMEMORY; } } // // Initialize Capabilities array // hr = BuildCapabilities(); if(FAILED(hr)) { return hr; } // // Build the device item tree, if it hasn't been built yet. // if (!m_pIDrvItemRoot) { LONG lDevErrVal; // // The WIA_CMD_SYNCHRONIZE command will build the item tree. // hr = drvDeviceCommand(NULL, 0, &WIA_CMD_SYNCHRONIZE, NULL, &lDevErrVal); } *ppIDrvItemRoot = m_pIDrvItemRoot; return hr; } /**************************************************************************\ * TestUsdDevice::drvUnInitializeWia * * Gets called when a client connection is going away. * * Arguments: * * pWiasContext - Pointer to the WIA Root item context of the client's * item tree. * * Return Value: * Status * * History: * * 30/12/1999 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvUnInitializeWia( BYTE *pWiasContext) { return S_OK; } /**************************************************************************\ * drvGetDeviceErrorStr * * Map a device error value to a string. * * Arguments: * * lFlags - Operation flags, unused. * lDevErrVal - Device error value. * ppszDevErrStr - Pointer to returned error string. * plDevErrVal - Pointer to the device error value. * * * Return Value: * * Status * * History: * * 10/2/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvGetDeviceErrorStr( LONG lFlags, LONG lDevErrVal, LPOLESTR *ppszDevErrStr, LONG *plDevErr) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvGetDeviceErrorStr"); *plDevErr = 0; // // Map device errors to a string to be placed in the event log. // switch (lDevErrVal) { case 0: *ppszDevErrStr = L"No Error"; break; default: *ppszDevErrStr = L"Device Error, Unknown Error"; return E_FAIL; } return S_OK; } /**************************************************************************\ * drvDeviceCommand * * Issue a command to the device. * * Arguments: * * pWiasContext - Pointer to the WIA item. * lFlags - Operation flags, unused. * plCommand - Pointer to command GUID. * ppWiaDrvItem - Optional pointer to returned item, unused. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvDeviceCommand( BYTE *pWiasContext, LONG lFlags, const GUID *plCommand, IWiaDrvItem **ppWiaDrvItem, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvDeviceCommand"); // // This device doesn't touch hardware, so set device error value to 0. // *plDevErrVal = 0; HRESULT hr; // // Check which command was issued // if (*plCommand == WIA_CMD_SYNCHRONIZE) { // // SYNCHRONIZE - Build the minidriver representation of // the current item list, if it doesn't exist. // if (!m_pIDrvItemRoot) { hr = BuildItemTree(); } else { hr = S_OK; } } else if (*plCommand == WIA_CMD_BUILD_DEVICE_TREE) { // // BUILD_DEVICE_TREE - Build the minidriver representation of // the current item list, if it doesn't exist. // if (!m_pIDrvItemRoot) { hr = BuildItemTree(); } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, WIA_CMD_BUILD_DEVICE_TREE, device tree allready exists")); hr = E_INVALIDARG; } } else if (*plCommand == WIA_CMD_DELETE_DEVICE_TREE) { // // DELETE_DEVICE_TREE - Delete the minidriver representation of // the current item list, if it exists. // if (m_pIDrvItemRoot) { hr = DeleteItemTree(); } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, WIA_CMD_DELETE_DEVICE_TREE, device tree doesn't exist")); hr = E_INVALIDARG; } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvDeviceCommand, unknown command")); hr = E_NOTIMPL; } return hr; } /**************************************************************************\ * TestUsdDevice::drvGetCapabilities * * Get supported device commands and events as an array of WIA_DEV_CAPS. * * Arguments: * * pWiasContext - Pointer to the WIA item, unused. * lFlags - Operation flags. * pcelt - Pointer to returned number of elements in * returned GUID array. * ppCapabilities - Pointer to returned GUID array. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 17/3/1999 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvGetCapabilities( BYTE *pWiasContext, LONG ulFlags, LONG *pcelt, WIA_DEV_CAP_DRV **ppCapabilities, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvGetCapabilites"); *plDevErrVal = 0; // // Return depends on flags. Flags specify whether we should return // commands, events, or both. // // switch (ulFlags) { case WIA_DEVICE_COMMANDS: // // Only commands // *pcelt = NUM_CAPABILITIES - NUM_EVENTS; *ppCapabilities = &g_Capabilities[NUM_EVENTS]; break; case WIA_DEVICE_EVENTS: // // Only events // *pcelt = NUM_EVENTS; *ppCapabilities = g_Capabilities; break; case (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS): // // Both events and commands // *pcelt = NUM_CAPABILITIES; *ppCapabilities = g_Capabilities; break; default: // // Flags is invalid // WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetCapabilities, flags was invalid")); return E_INVALIDARG; } return S_OK; } /**************************************************************************\ * drvGetWiaFormatInfo * * Returns an array of WIA_FORMAT_INFO structs, which specify the format * and media type pairs that are supported. * * Arguments: * * pWiasContext - Pointer to the WIA item context, unused. * lFlags - Operation flags, unused. * pcelt - Pointer to returned number of elements in * returned WIA_FORMAT_INFO array. * ppwfi - Pointer to returned WIA_FORMAT_INFO array. * plDevErrVal - Pointer to the device error value. * * Return Value: * * Status * * History: * * 11/18/1999 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvGetWiaFormatInfo( BYTE *pWiasContext, LONG lFlags, LONG *pcelt, WIA_FORMAT_INFO **ppwfi, LONG *plDevErrVal) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::drvGetWiaFormatInfo"); // // If it hasn't been done already, set up the g_wfiTable table // if (!g_wfiTable) { g_wfiTable = (WIA_FORMAT_INFO*) CoTaskMemAlloc(sizeof(WIA_FORMAT_INFO) * NUM_WIA_FORMAT_INFO); if (!g_wfiTable) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("drvGetWiaFormatInfo, out of memory")); return E_OUTOFMEMORY; } // // Set up the GUID Format / TYMED pairs // g_wfiTable[0].guidFormatID = WiaImgFmt_MEMORYBMP; g_wfiTable[0].lTymed = TYMED_CALLBACK; g_wfiTable[1].guidFormatID = WiaImgFmt_BMP; g_wfiTable[1].lTymed = TYMED_FILE; } *plDevErrVal = 0; *pcelt = NUM_WIA_FORMAT_INFO; *ppwfi = g_wfiTable; return S_OK; } /**************************************************************************\ * drvNotifyPnpEvent * * Pnp Event received by device manager. This is called when a Pnp event * is received for this device. * * Arguments: * * * * Return Value: * * Status * * History: * * Aug/3rd/1999 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvNotifyPnpEvent( const GUID *pEventGUID, BSTR bstrDeviceID, ULONG ulReserved) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL1, "TestUsdDevice::DrvNotifyPnpEvent"); // // Do nothing, since device is not Plug-and-play. // return (S_OK); } /******************************************************************************* * * P R I V A T E M E T H O D S * *******************************************************************************/ /**************************************************************************\ * AlignInPlace * * DWORD align a data buffer in place. * * Arguments: * * pBuffer - Pointer to the data buffer. * cbWritten - Size of the data in bytes. * lBytesPerScanLine - Number of bytes per scan line in the output data. * lBytesPerScanLineRaw - Number of bytes per scan line in the input data. * * Return Value: * * Status * * History: * * 10/29/1998 Original Version * \**************************************************************************/ UINT AlignInPlace( PBYTE pBuffer, LONG cbWritten, LONG lBytesPerScanLine, LONG lBytesPerScanLineRaw) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "::AlignInPlace"); if (lBytesPerScanLineRaw % 4) { UINT uiPadBytes = lBytesPerScanLine - lBytesPerScanLineRaw; UINT uiDevLinesWritten = cbWritten / lBytesPerScanLineRaw; PBYTE pSrc = pBuffer + cbWritten - 1; PBYTE pDst = pBuffer + (uiDevLinesWritten * lBytesPerScanLine) - 1; while (pSrc >= pBuffer) { pDst -= uiPadBytes; for (LONG i = 0; i < lBytesPerScanLineRaw; i++) { *pDst-- = *pSrc--; } } return uiDevLinesWritten * lBytesPerScanLine; } return cbWritten; } /**************************************************************************\ * TestUsdDevice::FillBufferFromFile * * Get the image data from the data source file. * * Arguments: * * pBuffer - Pointer to the data buffer. * lLength - Size of the data buffer in bytes. * pReceived - Number of bytes written to the buffer. * pdic - Pointer to the item context. * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::FillBufferFromFile( PBYTE pBuffer, LONG lLength, PLONG pReceived, PTESTMINIDRIVERITEMCONTEXT pdic) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::FillBufferFromFile"); HRESULT hr = S_OK; PBYTE pbSrc = pdic->pTestBmpBits; // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" FillBufferFromFile")); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pBuffer: %X", pBuffer)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lLength: %d", lLength)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pReceived: %X", pReceived)); while (((*pReceived) < lLength) && (pdic->lTotalWritten < pdic->lTotalRequested)){ // Return a scan line for (LONG i = 0; i < pdic->lBytesPerScanLineRaw; i++) { if ((pdic->lTestBmpLine < pdic->lTestBmpHeight) && (pdic->lTestBmpLine >= 0) && (i < pdic->lTestBmpBytesPerScanLine)) { // If the source bitmap still has data copy it. *pBuffer++ = *pbSrc++; *pReceived += 1; pdic->lTotalWritten++; } else { // If the source bitmap is out of line data, // pad out line with zero data. *pBuffer++ = 0; *pReceived += 1; pdic->lTotalWritten++; } } if (pdic->lTestBmpDir == 1) { pbSrc+= pdic->lTestBmpLinePad; pdic->lTestBmpLine++; } else { pbSrc -= (pdic->lTestBmpBytesPerScanLine * 2); pbSrc -= pdic->lTestBmpLinePad; pdic->lTestBmpLine--; } } pdic->pTestBmpBits = pbSrc; return hr; } /**************************************************************************\ * TestUsdDevice::FillBufferWithTestPattern * * Generate the image data from a test pattern. * * Arguments: * * pBuffer - Pointer to the data buffer. * lLength - Size of the data buffer in bytes. * pReceived - Number of bytes written to the buffer. * pItemContext - Pointer to the item context. * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::FillBufferWithTestPattern( PBYTE pBuffer, LONG lLength, PLONG pReceived, PTESTMINIDRIVERITEMCONTEXT pdic, PMINIDRV_TRANSFER_CONTEXT pmtc) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::FillBufferWithTestPattern"); HRESULT hr = S_OK; BYTE bColor; // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" FillBufferWithTestPattern")); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pBuffer: %X", pBuffer)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lLength: %d", lLength)); // WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pReceived: %X", pReceived)); while (((*pReceived) < lLength) && (pdic->lTotalWritten < pdic->lTotalRequested)) { switch (pmtc->lDepth) { case 1: if ((!pdic->lTotalWritten) || ((pdic->lTotalWritten % pdic->lBytesPerScanLineRaw) == 0)) { bColor = 0x55; } else { bColor = 0xAA; } *pBuffer++ = bColor; (*pReceived)++; pdic->lTotalWritten++; break; case 8: if ((!pdic->lTotalWritten) || ((pdic->lTotalWritten % pdic->lBytesPerScanLineRaw) == 0)) { bColor = 0x55; } else { if (LOBYTE(pBuffer) & 1) { bColor = 0xC0; } else { bColor = 0x00; } } *pBuffer++ = bColor; (*pReceived)++; pdic->lTotalWritten++; break; case 24: if ((!pdic->lTotalWritten) || ((pdic->lTotalWritten % pdic->lBytesPerScanLineRaw) == 0)) { bColor = 0x55; } else { bColor = 0xC0; } if (LOBYTE(pBuffer) & 1) { *pBuffer++ = bColor; *pBuffer++ = 0x00; *pBuffer++ = bColor; } else { *pBuffer++ = 0x00; *pBuffer++ = 0x00; *pBuffer++ = 0x00; } (*pReceived)+= 3; pdic->lTotalWritten += 3; break; default: WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::FillBufferWithTestPattern, unknown depth")); hr = E_FAIL; break; } } return hr; } /**************************************************************************\ * SetSrcBmp * * Set the correct source bitmap file associated with the current * bitdepth setting. * * Arguments: * * pWiasContext - wia item * * Return Value: * * Status * * History: * * 6/28/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::SetSrcBmp(BYTE *pWiasContext) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::SetSrcBmp"); HRESULT hr = S_OK; LONG lbitdepth = 0; // // Read WIA_IPA_DEPTH property, to get current setting // hr = wiasReadPropLong(pWiasContext, WIA_IPA_DEPTH, (LONG*)&lbitdepth, NULL, true); if (SUCCEEDED(hr)) { // // Build the path name of the data source file. // DWORD dwRet = GetTempPath(MAX_PATH, m_szSrcDataName); if (dwRet != 0) { switch(lbitdepth) { case 1: // 1-bit data requested _tcscat(m_szSrcDataName, DATA_1BIT_SRC_NAME); break; case 24:// 24-bit data requested _tcscat(m_szSrcDataName, DATA_24BIT_SRC_NAME); break; case 8: // 8-bit data requested default: WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("Defaulting to 8-bit")); _tcscat(m_szSrcDataName, DATA_8BIT_SRC_NAME); break; } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::SetSrcBmp, unable to get data source file name")); return STIERR_NOT_INITIALIZED; } // Make sure we can open the data source file. HANDLE hTestBmp = CreateFile(m_szSrcDataName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); // obtain last error information m_dwLastOperationError = ::GetLastError(); if (hTestBmp == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(m_dwLastOperationError); WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::SetSrcBmp, unable to open data source file:")); WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,(" %s", m_szSrcDataName)); WIAS_LHRESULT(g_pIWiaLog, hr); } else { WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" Source data: %s", m_szSrcDataName)); CloseHandle(hTestBmp); } } return hr; } /**************************************************************************\ * OpenTestBmp * * Open the test bitmap data file as a memory mapped file and retrieve * image size/format data. * * Arguments: * * pItemContext - Pointer to the item context. * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::OpenTestBmp( GUID guidFormatID, PTESTMINIDRIVERITEMCONTEXT pdic) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::OpenTestBmp"); HRESULT hr = S_OK; WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" OpenTestBmp")); // Data source file should be closed. if (pdic->hTestBmp != INVALID_HANDLE_VALUE) { CloseHandle(pdic->hTestBmp); pdic->hTestBmp = NULL; } // Open the data source file. pdic->hTestBmp = CreateFile(m_szSrcDataName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); // obtain last error information m_dwLastOperationError = ::GetLastError(); if (pdic->hTestBmp != INVALID_HANDLE_VALUE) { // Create a file mapping to the test bitmap. pdic->hTestBmpMap = NULL; pdic->hTestBmpMap = CreateFileMapping(pdic->hTestBmp, NULL, PAGE_READWRITE, 0, 0, NULL); if (pdic->hTestBmpMap != NULL) { // Map a view of the test bitmap. pdic->pTestBmp = NULL; pdic->pTestBmp = (PBYTE)MapViewOfFileEx(pdic->hTestBmpMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, NULL); if (pdic->pTestBmp != NULL) { // Retrieve image size/format data. PBYTE pb = pdic->pTestBmp; PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pb; PBITMAPINFO pbmi = (PBITMAPINFO)(pb + sizeof(BITMAPFILEHEADER)); // Validate bitmap. if (pbmFile->bfType == 'MB') { // get BMP size LONG lBmiSize = 0; hr = GetBmiSize(pbmi, &lBmiSize); if (SUCCEEDED(hr)) { // Reset total bytes written. pdic->lTotalWritten = 0; // Fill in test bitmap parameters. pdic->lTestBmpDepth = pbmi->bmiHeader.biBitCount; pdic->lTestBmpWidth = pbmi->bmiHeader.biWidth; pdic->lTestBmpHeight = pbmi->bmiHeader.biHeight; // Calculate data bytes per line in test bitmap. pdic->lTestBmpBytesPerScanLine = ((pdic->lTestBmpWidth * pdic->lTestBmpDepth) + 7) / 8; // Calculate pad bytes per line in test bitmap. pdic->lTestBmpLinePad = pdic->lTestBmpBytesPerScanLine % 4; if (pdic->lTestBmpLinePad) { pdic->lTestBmpLinePad = 4 - pdic->lTestBmpLinePad; } // Point to test bitmap image bits. pdic->pTestBmpBits = pb; pdic->pTestBmpBits += sizeof(BITMAPFILEHEADER); pdic->pTestBmpBits += lBmiSize; if (guidFormatID == WiaImgFmt_MEMORYBMP) { // Test bitmap is stored bottom up. If they want top // up, start at the last line in the file. pdic->lTestBmpDir = -1; pdic->lTestBmpLine = pdic->lTestBmpHeight - 1; pdic->pTestBmpBits += pdic->lTestBmpHeight * (pdic->lTestBmpBytesPerScanLine + pdic->lTestBmpLinePad); } else { // Test bitmap is stored bottom up. If they want bottom // up, start at the first line in the file. pdic->lTestBmpDir = 1; pdic->lTestBmpLine = 0; } WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("-- TestBmp Information --")); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpDepth: %d", pdic->lTestBmpDepth)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpWidth: %d", pdic->lTestBmpWidth)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpHeight: %d", pdic->lTestBmpHeight)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" pTestBmpBits: %X", pdic->pTestBmpBits)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpBytesPerScanLine: %d", pdic->lTestBmpBytesPerScanLine)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpLinePad: %d", pdic->lTestBmpLinePad)); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" lTestBmpDir: %d", pdic->lTestBmpDir)); return hr; } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::OpenTestBmp, invalid BMI")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::OpenTestBmp, not a valid bitmap")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::OpenTestBmp, MapViewOfFileEx failed")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::OpenTestBmp, CreateFilemapping failed")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::OpenTestBmp, unable to open data source file:")); } if (SUCCEEDED(hr)) { hr = HRESULT_FROM_WIN32(m_dwLastOperationError); } WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,(" %s", m_szSrcDataName)); WIAS_LHRESULT(g_pIWiaLog, hr); CloseTestBmp(pdic); return hr; } /**************************************************************************\ * CloseTestBmp * * Close the test bitmap data file and clear the image size/format data. * * Arguments: * * pItemContext - Pointer to the item context. * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::CloseTestBmp( PTESTMINIDRIVERITEMCONTEXT pItemContext) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::CloseTestBmp"); pItemContext->lTestBmpDepth = 0; pItemContext->lTestBmpWidth = 0; pItemContext->lTestBmpHeight = 0; pItemContext->pTestBmpBits = NULL; pItemContext->lTestBmpLine = 0; // Unmap data source file. if (pItemContext->pTestBmp != NULL) { UnmapViewOfFile(pItemContext->pTestBmp); pItemContext->pTestBmp = NULL; } // Close data source file mapping. if (pItemContext->hTestBmpMap != NULL) { CloseHandle(pItemContext->hTestBmpMap); pItemContext->hTestBmpMap = NULL; } // Close data source file handle. if (pItemContext->hTestBmp != INVALID_HANDLE_VALUE) { CloseHandle(pItemContext->hTestBmp); pItemContext->hTestBmp = INVALID_HANDLE_VALUE; } return S_OK; } /**************************************************************************\ * Scan * * Get the image data from the device hardware. * * Arguments: * * iPhase - Phase of the scan (START, CONTINUE, END). * pBuffer - Pointer to the data buffer. * lLength - Size of the data buffer in bytes. * pReceived - Number of bytes written to the buffer. * pItemContext - Pointer to the item context. * * Return Value: * * Status * * History: * * 11/18/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::Scan( GUID guidFormatID, LONG iPhase, PBYTE pBuffer, LONG lLength, PLONG pReceived, PTESTMINIDRIVERITEMCONTEXT pItemContext, PMINIDRV_TRANSFER_CONTEXT pmtc) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::Scan"); HRESULT hr = S_OK; static HRESULT hrOpen = S_FALSE; if (!pItemContext) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Scan, NULL pItemContext")); DebugBreak(); return E_INVALIDARG; } switch (iPhase) { case START: hrOpen = OpenTestBmp(guidFormatID, pItemContext); if (FAILED(hr)) { return hrOpen; } case CONTINUE: if (pReceived && pBuffer) { *pReceived = 0; if ((pmtc->lDepth == pItemContext->lTestBmpDepth) && (hrOpen == S_OK)) { // If we have a scan request for the same format // as the test bitmap, fill the buffer from the // test bitmap. hr = FillBufferFromFile(pBuffer, lLength, pReceived, pItemContext); } else { // The test bitmap doesn't match the request, // fill the buffer with a test pattern. hr = FillBufferWithTestPattern(pBuffer, lLength, pReceived, pItemContext, pmtc); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Scan, null parameter")); hr = E_INVALIDARG; } break; case END: hr = CloseTestBmp(pItemContext); hrOpen = S_FALSE; break; default: WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Scan, unknown phase")); hr = E_FAIL; } return hr; } /**************************************************************************\ * UnlinkItemTree * * Call device manager to unlink and release our reference to * all items in the driver item tree. * * Arguments: * * * * Return Value: * * Status * * History: * * 10/2/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::DeleteItemTree(void) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::DeleteItemTree"); // // If no tree, return. // if (!m_pIDrvItemRoot) { return S_OK; } // // Call device manager to unlink the driver item tree. // HRESULT hr = m_pIDrvItemRoot->UnlinkItemTree(WiaItemTypeDisconnected); if (SUCCEEDED(hr)) { m_pIDrvItemRoot = NULL; } return hr; } /**************************************************************************\ * BuildItemTree * * The device uses the WIA Service functions to build up a tree of * device items. The test scanner supports only a single scanning item so * build a device item tree with only one child off the root. * * Arguments: * * * * Return Value: * * Status * * History: * * 10/2/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::BuildItemTree(void) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "TestUsdDevice::BuildItemTree"); WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("TestUsdDevice::BuildItemTree")); // // The device item tree must not exist. // WIAS_ASSERT( (g_hInst), (m_pIDrvItemRoot == NULL)); // // Call the class driver to create the root item. // HRESULT hr = E_FAIL; // // Name the root. // BSTR bstrRoot = NULL; hr = GetBSTRResourceString(IDS_FULLROOTITEM_NAME,&bstrRoot,TRUE); if (bstrRoot) { hr = wiasCreateDrvItem(WiaItemTypeFolder | WiaItemTypeDevice | WiaItemTypeRoot, bstrRoot, bstrRoot, (IWiaMiniDrv *)this, sizeof(TESTMINIDRIVERITEMCONTEXT), NULL, &m_pIDrvItemRoot); SysFreeString(bstrRoot); if (FAILED(hr)) { return hr; } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, unable to allocate item name")); return E_OUTOFMEMORY; } // // Create and add the Top/Front and Bottom/Back device items. // for (INT i = 0; i < NUM_DEVICE_ITEM; i++) { // // Build the item names. // BSTR bstrItemName = NULL; BSTR bstrFullItemName = NULL; bstrItemName = NULL; hr = GetBSTRResourceString(IDS_TOPITEM_NAME,&bstrItemName,TRUE); if (SUCCEEDED(hr)) { hr = GetBSTRResourceString(IDS_FULLTOPITEM_NAME,&bstrFullItemName,TRUE); if (SUCCEEDED(hr)) { // // Call the class driver to create another driver item. // This will be inserted as the child item. // PTESTMINIDRIVERITEMCONTEXT pItemContext; IWiaDrvItem *pItem = NULL; hr = wiasCreateDrvItem(WiaItemTypeFile | WiaItemTypeImage | WiaItemTypeDevice, bstrItemName, bstrFullItemName, (IWiaMiniDrv *)this, sizeof(TESTMINIDRIVERITEMCONTEXT), (PBYTE*) &pItemContext, &pItem); if (SUCCEEDED(hr)) { // // Initialize device specific context. // memset(pItemContext, 0, sizeof(TESTMINIDRIVERITEMCONTEXT)); pItemContext->lSize = sizeof(TESTMINIDRIVERITEMCONTEXT); // // Call the class driver to add pItem to the folder // m_pIDrvItemRoot (i.e. make pItem a child of // m_pIDrvItemRoot). // hr = pItem->AddItemToFolder(m_pIDrvItemRoot); if (FAILED(hr)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, AddItemToFolder failed")); } } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, wiasCreateDrvItem failed")); } // // free the BSTR allocated by the BSTRResourceString helper // SysFreeString(bstrFullItemName); } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, unable to allocate full item name")); hr = E_OUTOFMEMORY; } // // free the BSTR allocated by the BSTRResourceString helper // SysFreeString(bstrItemName); } else { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("BuildItemTree, unable to allocate item name")); hr = E_OUTOFMEMORY; } break; // Error if here, quit iterating. } if (FAILED(hr)) { DeleteItemTree(); } return hr; } /**************************************************************************\ * GetBmiSize * * Get the size of the BMI structure. We should never see biCompression * set to BI_RLE. * * Arguments: * * pbmi - Pointer to input BITMAPINFO structure. * plBmiSize - Pointer output BMI size. * * Return Value: * * Size of * * History: * * 1/19/1999 Original Version * \**************************************************************************/ HRESULT _stdcall GetBmiSize(PBITMAPINFO pbmi, LONG *plBmiSize) { CWiaLogProc WIAS_LOGPROC(g_pIWiaLog, WIALOG_NO_RESOURCE_ID, WIALOG_LEVEL3, "::GetBmiSize"); // check plBmiSize pointer to see if it can be written to properly if (IsBadWritePtr(plBmiSize, sizeof(LONG))) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetBmiSize, bad plBmiSize")); return E_POINTER; } LONG lSize = pbmi->bmiHeader.biSize; if ((pbmi->bmiHeader.biCompression == BI_RLE8) || (pbmi->bmiHeader.biCompression == BI_RLE4)) { WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetBmiSize, BI_RLE not allowed")); return E_INVALIDARG; } // determine the size of bits and palette data if ((pbmi->bmiHeader.biBitCount == 24) || ((pbmi->bmiHeader.biBitCount == 32) && (pbmi->bmiHeader.biCompression == BI_RGB))) { // no color table case, no colors unless stated lSize += sizeof(RGBQUAD) * pbmi->bmiHeader.biClrUsed; } else if (((pbmi->bmiHeader.biBitCount == 32) && (pbmi->bmiHeader.biCompression == BI_BITFIELDS)) || (pbmi->bmiHeader.biBitCount == 16)) { // bitfields case lSize += 3 * sizeof(RGBQUAD); } else if (pbmi->bmiHeader.biBitCount == 1) { // palette cases LONG lPal = pbmi->bmiHeader.biClrUsed; if ((lPal == 0) || (lPal > 2)) { lPal = 2; } lSize += lPal * sizeof(RGBQUAD); } else if (pbmi->bmiHeader.biBitCount == 4) { // palette case LONG lPal = pbmi->bmiHeader.biClrUsed; if ((lPal == 0) || (lPal > 16)) { lPal = 16; } lSize += lPal * sizeof(RGBQUAD); } else if (pbmi->bmiHeader.biBitCount == 8){ // palette case LONG lPal = pbmi->bmiHeader.biClrUsed; if ((lPal == 0) || (lPal > 256)){ lPal = 256; } lSize += lPal * sizeof(RGBQUAD); } // assign calculated size to returned value *plBmiSize = lSize; return S_OK; } /**************************************************************************\ * GetBSTRResourceString * * This helper gets a BSTR from a resource location * * Arguments: * * lResourceID - Resource ID of the target BSTR value * pBSTR - pointer to a BSTR value (caller must free this string) * bLocal - TRUE - for local resources, FALSE - for wiaservc resources * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::GetBSTRResourceString(LONG lResourceID,BSTR *pBSTR,BOOL bLocal) { HRESULT hr = S_OK; TCHAR szStringValue[255]; if(bLocal) { // // We are looking for a resource in our own private resource file // LoadString(g_hInst,lResourceID,szStringValue,sizeof(szStringValue)); // // NOTE: caller must free this allocated BSTR // #ifdef UNICODE *pBSTR = SysAllocString(szStringValue); #else WCHAR wszStringValue[255]; // // convert szStringValue from char* to unsigned short* (ANSI only) // MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szStringValue, lstrlenA(szStringValue)+1, wszStringValue, sizeof(wszStringValue)); *pBSTR = SysAllocString(wszStringValue); #endif } else { // // We are looking for a resource in the wiaservc's resource file // hr = E_NOTIMPL; } return hr; } /**************************************************************************\ * GetOLESTRResourceString * * This helper gets a LPOLESTR from a resource location * * Arguments: * * lResourceID - Resource ID of the target BSTR value * ppsz - pointer to a OLESTR value (caller must free this string) * bLocal - TRUE - for local resources, FALSE - for wiaservc resources * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::GetOLESTRResourceString(LONG lResourceID,LPOLESTR *ppsz,BOOL bLocal) { HRESULT hr = S_OK; TCHAR szStringValue[255]; if(bLocal) { // // We are looking for a resource in our own private resource file // LoadString(g_hInst,lResourceID,szStringValue,sizeof(szStringValue)); // // NOTE: caller must free this allocated BSTR // #ifdef UNICODE *ppsz = NULL; *ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(szStringValue)); if(*ppsz != NULL) { wcscpy(*ppsz,szStringValue); } else { return E_OUTOFMEMORY; } #else WCHAR wszStringValue[255]; // // convert szStringValue from char* to unsigned short* (ANSI only) // MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szStringValue, lstrlenA(szStringValue)+1, wszStringValue, sizeof(wszStringValue)); *ppsz = NULL; *ppsz = (LPOLESTR)CoTaskMemAlloc(sizeof(wszStringValue)); if(*ppsz != NULL) { wcscpy(*ppsz,wszStringValue); } else { return E_OUTOFMEMORY; } #endif } else { // // We are looking for a resource in the wiaservc's resource file // hr = E_NOTIMPL; } return hr; } /**************************************************************************\ * BuildRootItemProperties * * This helper initialize the global arrays used for Property intialization. * note: These globals are defined in ( DEFPROP.H ) * * [Array Name] [Description] [Array Type] * * g_pszRootItemDefaults - Property name array (LPOLESTR) * g_piRootItemDefaults - Property ID array (PROPID) * g_pvRootItemDefaults - Property Variant array (PROPVARIANT) * g_psRootItemDefaults - Property Spec array (PROPSPEC) * g_wpiRootItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO) * * * Arguments: * * none * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::BuildRootItemProperties() { HRESULT hr = S_OK; // start index after initial properties INT iPropArrayIndex = NUM_ROOTITEMDEFAULTS; // Intialize WIA_DPS_HORIZONTAL_BED_SIZE g_pszRootItemDefaults[0] = WIA_DPS_HORIZONTAL_BED_SIZE_STR; g_piRootItemDefaults [0] = WIA_DPS_HORIZONTAL_BED_SIZE; g_pvRootItemDefaults [0].lVal = HORIZONTAL_BED_SIZE; g_pvRootItemDefaults [0].vt = VT_I4; g_psRootItemDefaults [0].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [0].propid = g_piRootItemDefaults [0]; g_wpiRootItemDefaults[0].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[0].vt = g_pvRootItemDefaults [0].vt; // Intialize WIA_DPS_VERTICAL_BED_SIZE g_pszRootItemDefaults[1] = WIA_DPS_VERTICAL_BED_SIZE_STR; g_piRootItemDefaults [1] = WIA_DPS_VERTICAL_BED_SIZE; g_pvRootItemDefaults [1].lVal = VERTICAL_BED_SIZE; g_pvRootItemDefaults [1].vt = VT_I4; g_psRootItemDefaults [1].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [1].propid = g_piRootItemDefaults [1]; g_wpiRootItemDefaults[1].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[1].vt = g_pvRootItemDefaults [1].vt; // Intialize WIA_IPA_ACCESS_RIGHTS g_pszRootItemDefaults[2] = WIA_IPA_ACCESS_RIGHTS_STR; g_piRootItemDefaults [2] = WIA_IPA_ACCESS_RIGHTS; g_pvRootItemDefaults [2].lVal = WIA_ITEM_READ|WIA_ITEM_WRITE; g_pvRootItemDefaults [2].vt = VT_UI4; g_psRootItemDefaults [2].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [2].propid = g_piRootItemDefaults [2]; g_wpiRootItemDefaults[2].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[2].vt = g_pvRootItemDefaults [2].vt; // Intialize WIA_DPS_OPTICAL_XRES g_pszRootItemDefaults[3] = WIA_DPS_OPTICAL_XRES_STR; g_piRootItemDefaults [3] = WIA_DPS_OPTICAL_XRES; g_pvRootItemDefaults [3].lVal = OPTICAL_XRESOLUTION; g_pvRootItemDefaults [3].vt = VT_I4; g_psRootItemDefaults [3].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [3].propid = g_piRootItemDefaults [3]; g_wpiRootItemDefaults[3].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[3].vt = g_pvRootItemDefaults [3].vt; // Intialize WIA_DPS_OPTICAL_YRES g_pszRootItemDefaults[4] = WIA_DPS_OPTICAL_YRES_STR; g_piRootItemDefaults [4] = WIA_DPS_OPTICAL_YRES; g_pvRootItemDefaults [4].lVal = OPTICAL_YRESOLUTION; g_pvRootItemDefaults [4].vt = VT_I4; g_psRootItemDefaults [4].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [4].propid = g_piRootItemDefaults [4]; g_wpiRootItemDefaults[4].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[4].vt = g_pvRootItemDefaults [4].vt; // Initialize WIA_DPA_FIRMWARE_VERSION g_pszRootItemDefaults[5] = WIA_DPA_FIRMWARE_VERSION_STR; g_piRootItemDefaults [5] = WIA_DPA_FIRMWARE_VERSION; g_pvRootItemDefaults [5].bstrVal = SysAllocString(WIATSCAN_FIRMWARE_VERSION); g_pvRootItemDefaults [5].vt = VT_BSTR; g_psRootItemDefaults [5].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [5].propid = g_piRootItemDefaults [5]; g_wpiRootItemDefaults[5].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiRootItemDefaults[5].vt = g_pvRootItemDefaults [5].vt; // Initialize WIA_IPA_ITEM_FLAGS g_pszRootItemDefaults[6] = WIA_IPA_ITEM_FLAGS_STR; g_piRootItemDefaults [6] = WIA_IPA_ITEM_FLAGS; g_pvRootItemDefaults [6].lVal = WiaItemTypeRoot|WiaItemTypeFolder|WiaItemTypeDevice; g_pvRootItemDefaults [6].vt = VT_I4; g_psRootItemDefaults [6].ulKind = PRSPEC_PROPID; g_psRootItemDefaults [6].propid = g_piRootItemDefaults [6]; g_wpiRootItemDefaults[6].lAccessFlags = WIA_PROP_READ|WIA_PROP_FLAG; g_wpiRootItemDefaults[6].vt = g_pvRootItemDefaults [6].vt; g_wpiRootItemDefaults[6].ValidVal.Flag.Nom = g_pvRootItemDefaults [6].lVal; g_wpiRootItemDefaults[6].ValidVal.Flag.ValidBits = WiaItemTypeRoot|WiaItemTypeFolder|WiaItemTypeDevice; if(g_bHasADF) { // // Initialize Automatic Document Feeder properties // } if(g_bHasTPA) { // // Initialize Transparant Adapter properties // } return hr; } /**************************************************************************\ * BuildTopItemProperties * * This helper initialize the global arrays used for Property intialization. * note: These globals are defined in ( DEFPROP.H ) * * [Array Name] [Description] [Array Type] * * g_pszItemDefaults - Property name array (LPOLESTR) * g_piItemDefaults - Property ID array (PROPID) * g_pvItemDefaults - Property Variant array (PROPVARIANT) * g_psItemDefaults - Property Spec array (PROPSPEC) * g_wpiItemDefaults - WIA Property Info array (WIA_PROPERTY_INFO) * * Arguments: * * none * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::BuildTopItemProperties() { HRESULT hr = S_OK; // Intialize WIA_IPS_XRES (RANGE) g_pszItemDefaults[0] = WIA_IPS_XRES_STR; g_piItemDefaults [0] = WIA_IPS_XRES; g_pvItemDefaults [0].lVal = INITIAL_XRESOLUTION; g_pvItemDefaults [0].vt = VT_I4; g_psItemDefaults [0].ulKind = PRSPEC_PROPID; g_psItemDefaults [0].propid = g_piItemDefaults [0]; g_wpiItemDefaults[0].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[0].vt = g_pvItemDefaults [0].vt; g_wpiItemDefaults[0].ValidVal.Range.Inc = 1; g_wpiItemDefaults[0].ValidVal.Range.Min = 12; g_wpiItemDefaults[0].ValidVal.Range.Max = 1600; g_wpiItemDefaults[0].ValidVal.Range.Nom = g_pvItemDefaults [0].lVal; // Intialize WIA_IPS_YRES (RANGE) g_pszItemDefaults[1] = WIA_IPS_YRES_STR; g_piItemDefaults [1] = WIA_IPS_YRES; g_pvItemDefaults [1].lVal = INITIAL_YRESOLUTION; g_pvItemDefaults [1].vt = VT_I4; g_psItemDefaults [1].ulKind = PRSPEC_PROPID; g_psItemDefaults [1].propid = g_piItemDefaults [1]; g_wpiItemDefaults[1].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[1].vt = g_pvItemDefaults [1].vt; g_wpiItemDefaults[1].ValidVal.Range.Inc = 1; g_wpiItemDefaults[1].ValidVal.Range.Min = 12; g_wpiItemDefaults[1].ValidVal.Range.Max = 1600; g_wpiItemDefaults[1].ValidVal.Range.Nom = g_pvItemDefaults [1].lVal; // Intialize WIA_IPS_XEXTENT (RANGE) g_pszItemDefaults[2] = WIA_IPS_XEXTENT_STR; g_piItemDefaults [2] = WIA_IPS_XEXTENT; g_pvItemDefaults [2].lVal = (INITIAL_XRESOLUTION * HORIZONTAL_BED_SIZE)/1000; g_pvItemDefaults [2].vt = VT_I4; g_psItemDefaults [2].ulKind = PRSPEC_PROPID; g_psItemDefaults [2].propid = g_piItemDefaults [2]; g_wpiItemDefaults[2].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[2].vt = g_pvItemDefaults [2].vt; g_wpiItemDefaults[2].ValidVal.Range.Inc = 1; g_wpiItemDefaults[2].ValidVal.Range.Min = 1; g_wpiItemDefaults[2].ValidVal.Range.Max = g_pvItemDefaults [2].lVal; g_wpiItemDefaults[2].ValidVal.Range.Nom = g_pvItemDefaults [2].lVal; // Intialize WIA_IPS_YEXTENT (RANGE) g_pszItemDefaults[3] = WIA_IPS_YEXTENT_STR; g_piItemDefaults [3] = WIA_IPS_YEXTENT; g_pvItemDefaults [3].lVal = (INITIAL_YRESOLUTION * VERTICAL_BED_SIZE)/1000;; g_pvItemDefaults [3].vt = VT_I4; g_psItemDefaults [3].ulKind = PRSPEC_PROPID; g_psItemDefaults [3].propid = g_piItemDefaults [3]; g_wpiItemDefaults[3].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[3].vt = g_pvItemDefaults [3].vt; g_wpiItemDefaults[3].ValidVal.Range.Inc = 1; g_wpiItemDefaults[3].ValidVal.Range.Min = 1; g_wpiItemDefaults[3].ValidVal.Range.Max = g_pvItemDefaults [3].lVal; g_wpiItemDefaults[3].ValidVal.Range.Nom = g_pvItemDefaults [3].lVal; // Intialize WIA_IPS_XPOS (RANGE) g_pszItemDefaults[4] = WIA_IPS_XPOS_STR; g_piItemDefaults [4] = WIA_IPS_XPOS; g_pvItemDefaults [4].lVal = 0; g_pvItemDefaults [4].vt = VT_I4; g_psItemDefaults [4].ulKind = PRSPEC_PROPID; g_psItemDefaults [4].propid = g_piItemDefaults [4]; g_wpiItemDefaults[4].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[4].vt = g_pvItemDefaults [4].vt; g_wpiItemDefaults[4].ValidVal.Range.Inc = 1; g_wpiItemDefaults[4].ValidVal.Range.Min = 0; g_wpiItemDefaults[4].ValidVal.Range.Max = (g_wpiItemDefaults[2].ValidVal.Range.Max - 1); g_wpiItemDefaults[4].ValidVal.Range.Nom = g_pvItemDefaults [4].lVal; // Intialize WIA_IPS_YPOS (RANGE) g_pszItemDefaults[5] = WIA_IPS_YPOS_STR; g_piItemDefaults [5] = WIA_IPS_YPOS; g_pvItemDefaults [5].lVal = 0; g_pvItemDefaults [5].vt = VT_I4; g_psItemDefaults [5].ulKind = PRSPEC_PROPID; g_psItemDefaults [5].propid = g_piItemDefaults [5]; g_wpiItemDefaults[5].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[5].vt = g_pvItemDefaults [5].vt; g_wpiItemDefaults[5].ValidVal.Range.Inc = 1; g_wpiItemDefaults[5].ValidVal.Range.Min = 0; g_wpiItemDefaults[5].ValidVal.Range.Max = (g_wpiItemDefaults[3].ValidVal.Range.Max - 1); g_wpiItemDefaults[5].ValidVal.Range.Nom = g_pvItemDefaults [5].lVal; // Intialize WIA_IPA_DATATYPE (LIST) g_pszItemDefaults[6] = WIA_IPA_DATATYPE_STR; g_piItemDefaults [6] = WIA_IPA_DATATYPE; g_pvItemDefaults [6].lVal = INITIAL_DATATYPE; g_pvItemDefaults [6].vt = VT_I4; g_psItemDefaults [6].ulKind = PRSPEC_PROPID; g_psItemDefaults [6].propid = g_piItemDefaults [6]; g_wpiItemDefaults[6].lAccessFlags = WIA_PROP_RW|WIA_PROP_LIST; g_wpiItemDefaults[6].vt = g_pvItemDefaults [6].vt; g_wpiItemDefaults[6].ValidVal.List.pList = (BYTE*)g_DataTypeArray; g_wpiItemDefaults[6].ValidVal.List.Nom = g_pvItemDefaults [6].lVal; g_wpiItemDefaults[6].ValidVal.List.cNumList = NUM_DATATYPES; // Intialize WIA_IPA_DEPTH (LIST) g_pszItemDefaults[7] = WIA_IPA_DEPTH_STR; g_piItemDefaults [7] = WIA_IPA_DEPTH; g_pvItemDefaults [7].lVal = INITIAL_BITDEPTH; g_pvItemDefaults [7].vt = VT_I4; g_psItemDefaults [7].ulKind = PRSPEC_PROPID; g_psItemDefaults [7].propid = g_piItemDefaults [7]; g_wpiItemDefaults[7].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[7].vt = g_pvItemDefaults [7].vt; // Intialize WIA_IPS_BRIGHTNESS (RANGE) g_pszItemDefaults[8] = WIA_IPS_BRIGHTNESS_STR; g_piItemDefaults [8] = WIA_IPS_BRIGHTNESS; g_pvItemDefaults [8].lVal = INITIAL_BRIGHTNESS; g_pvItemDefaults [8].vt = VT_I4; g_psItemDefaults [8].ulKind = PRSPEC_PROPID; g_psItemDefaults [8].propid = g_piItemDefaults [8]; g_wpiItemDefaults[8].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[8].vt = g_pvItemDefaults [8].vt; g_wpiItemDefaults[8].ValidVal.Range.Inc = 1; g_wpiItemDefaults[8].ValidVal.Range.Min = -127; g_wpiItemDefaults[8].ValidVal.Range.Max = 128; g_wpiItemDefaults[8].ValidVal.Range.Nom = g_pvItemDefaults [8].lVal; // Intialize WIA_IPS_CONTRAST (RANGE) g_pszItemDefaults[9] = WIA_IPS_CONTRAST_STR; g_piItemDefaults [9] = WIA_IPS_CONTRAST; g_pvItemDefaults [9].lVal = INITIAL_CONTRAST; g_pvItemDefaults [9].vt = VT_I4; g_psItemDefaults [9].ulKind = PRSPEC_PROPID; g_psItemDefaults [9].propid = g_piItemDefaults [9]; g_wpiItemDefaults[9].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[9].vt = g_pvItemDefaults [9].vt; g_wpiItemDefaults[9].ValidVal.Range.Inc = 1; g_wpiItemDefaults[9].ValidVal.Range.Min = -127; g_wpiItemDefaults[9].ValidVal.Range.Max = 128; g_wpiItemDefaults[9].ValidVal.Range.Nom = g_pvItemDefaults [9].lVal; // Intialize WIA_IPS_CUR_INTENT (FLAG) g_pszItemDefaults[10] = WIA_IPS_CUR_INTENT_STR; g_piItemDefaults [10] = WIA_IPS_CUR_INTENT; g_pvItemDefaults [10].lVal = WIA_INTENT_NONE; g_pvItemDefaults [10].vt = VT_I4; g_psItemDefaults [10].ulKind = PRSPEC_PROPID; g_psItemDefaults [10].propid = g_piItemDefaults [10]; g_wpiItemDefaults[10].lAccessFlags = WIA_PROP_RW|WIA_PROP_FLAG; g_wpiItemDefaults[10].vt = g_pvItemDefaults [10].vt; g_wpiItemDefaults[10].ValidVal.Flag.Nom = g_pvItemDefaults [10].lVal; g_wpiItemDefaults[10].ValidVal.Flag.ValidBits = WIA_INTENT_SIZE_MASK | WIA_INTENT_IMAGE_TYPE_MASK; // Intialize WIA_IPA_PIXELS_PER_LINE (NONE) g_pszItemDefaults[11] = WIA_IPA_PIXELS_PER_LINE_STR; g_piItemDefaults [11] = WIA_IPA_PIXELS_PER_LINE; g_pvItemDefaults [11].lVal = (INITIAL_XRESOLUTION * HORIZONTAL_BED_SIZE)/1000; g_pvItemDefaults [11].vt = VT_I4; g_psItemDefaults [11].ulKind = PRSPEC_PROPID; g_psItemDefaults [11].propid = g_piItemDefaults [11]; g_wpiItemDefaults[11].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[11].vt = g_pvItemDefaults [11].vt; // Intialize WIA_IPA_NUMER_OF_LINES (NONE) g_pszItemDefaults[12] = WIA_IPA_NUMBER_OF_LINES_STR; g_piItemDefaults [12] = WIA_IPA_NUMBER_OF_LINES; g_pvItemDefaults [12].lVal = (INITIAL_YRESOLUTION * VERTICAL_BED_SIZE)/1000; g_pvItemDefaults [12].vt = VT_I4; g_psItemDefaults [12].ulKind = PRSPEC_PROPID; g_psItemDefaults [12].propid = g_piItemDefaults [12]; g_wpiItemDefaults[12].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[12].vt = g_pvItemDefaults [12].vt; // Intialize WIA_IPA_ITEM_TIME (NONE) g_pszItemDefaults[13] = WIA_IPA_ITEM_TIME_STR; g_piItemDefaults [13] = WIA_IPA_ITEM_TIME; g_pvItemDefaults [13].lVal = 0; g_pvItemDefaults [13].vt = VT_VECTOR|VT_I4; g_psItemDefaults [13].ulKind = PRSPEC_PROPID; g_psItemDefaults [13].propid = g_piItemDefaults [13]; g_wpiItemDefaults[13].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[13].vt = g_pvItemDefaults [13].vt; // Intialize WIA_IPA_PREFERRED_FORMAT (NONE) g_pszItemDefaults[14] = WIA_IPA_PREFERRED_FORMAT_STR; g_piItemDefaults [14] = WIA_IPA_PREFERRED_FORMAT; g_pvItemDefaults [14].puuid = INITIAL_FORMAT; g_pvItemDefaults [14].vt = VT_CLSID; g_psItemDefaults [14].ulKind = PRSPEC_PROPID; g_psItemDefaults [14].propid = g_piItemDefaults [14]; g_wpiItemDefaults[14].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[14].vt = g_pvItemDefaults [14].vt; // Intialize WIA_IPA_ITEM_SIZE (NONE) g_pszItemDefaults[15] = WIA_IPA_ITEM_SIZE_STR; g_piItemDefaults [15] = WIA_IPA_ITEM_SIZE; g_pvItemDefaults [15].lVal = 0; g_pvItemDefaults [15].vt = VT_I4; g_psItemDefaults [15].ulKind = PRSPEC_PROPID; g_psItemDefaults [15].propid = g_piItemDefaults [15]; g_wpiItemDefaults[15].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[15].vt = g_pvItemDefaults [15].vt; // Intialize WIA_IPS_THRESHOLD (RANGE) g_pszItemDefaults[16] = WIA_IPS_THRESHOLD_STR; g_piItemDefaults [16] = WIA_IPS_THRESHOLD; g_pvItemDefaults [16].lVal = 0; g_pvItemDefaults [16].vt = VT_I4; g_psItemDefaults [16].ulKind = PRSPEC_PROPID; g_psItemDefaults [16].propid = g_piItemDefaults [16]; g_wpiItemDefaults[16].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[16].vt = g_pvItemDefaults [16].vt; g_wpiItemDefaults[16].ValidVal.Range.Inc = 1; g_wpiItemDefaults[16].ValidVal.Range.Min = -127; g_wpiItemDefaults[16].ValidVal.Range.Max = 128; g_wpiItemDefaults[16].ValidVal.Range.Nom = g_pvItemDefaults [16].lVal; // Intialize WIA_IPA_FORMAT (LIST) g_pszItemDefaults[17] = WIA_IPA_FORMAT_STR; g_piItemDefaults [17] = WIA_IPA_FORMAT; g_pvItemDefaults [17].puuid = INITIAL_FORMAT; g_pvItemDefaults [17].vt = VT_CLSID; g_psItemDefaults [17].ulKind = PRSPEC_PROPID; g_psItemDefaults [17].propid = g_piItemDefaults [17]; g_wpiItemDefaults[17].lAccessFlags = WIA_PROP_RW|WIA_PROP_LIST; g_wpiItemDefaults[17].vt = g_pvItemDefaults [17].vt; g_wpiItemDefaults[17].ValidVal.ListGuid.pList = (GUID*)g_pInitialFormatArray; g_wpiItemDefaults[17].ValidVal.ListGuid.Nom = *g_pvItemDefaults [17].puuid; g_wpiItemDefaults[17].ValidVal.ListGuid.cNumList = NUM_INITIALFORMATS; // Intialize WIA_IPA_TYMED (LIST) g_pszItemDefaults[18] = WIA_IPA_TYMED_STR; g_piItemDefaults [18] = WIA_IPA_TYMED; g_pvItemDefaults [18].lVal = INITIAL_TYMED; g_pvItemDefaults [18].vt = VT_I4; g_psItemDefaults [18].ulKind = PRSPEC_PROPID; g_psItemDefaults [18].propid = g_piItemDefaults [18]; g_wpiItemDefaults[18].lAccessFlags = WIA_PROP_RW|WIA_PROP_LIST; g_wpiItemDefaults[18].vt = g_pvItemDefaults [18].vt; g_wpiItemDefaults[18].ValidVal.List.pList = (BYTE*)g_TYMEDArray; g_wpiItemDefaults[18].ValidVal.List.Nom = g_pvItemDefaults [18].lVal; g_wpiItemDefaults[18].ValidVal.List.cNumList = NUM_TYMEDS; // Intialize WIA_IPA_CHANNELS_PER_PIXEL (NONE) g_pszItemDefaults[19] = WIA_IPA_CHANNELS_PER_PIXEL_STR; g_piItemDefaults [19] = WIA_IPA_CHANNELS_PER_PIXEL; g_pvItemDefaults [19].lVal = INITIAL_CHANNELS_PER_PIXEL; g_pvItemDefaults [19].vt = VT_I4; g_psItemDefaults [19].ulKind = PRSPEC_PROPID; g_psItemDefaults [19].propid = g_piItemDefaults [19]; g_wpiItemDefaults[19].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[19].vt = g_pvItemDefaults [19].vt; // Intialize WIA_IPA_BITS_PER_CHANNEL (NONE) g_pszItemDefaults[20] = WIA_IPA_BITS_PER_CHANNEL_STR; g_piItemDefaults [20] = WIA_IPA_BITS_PER_CHANNEL; g_pvItemDefaults [20].lVal = INITIAL_BITS_PER_CHANNEL; g_pvItemDefaults [20].vt = VT_I4; g_psItemDefaults [20].ulKind = PRSPEC_PROPID; g_psItemDefaults [20].propid = g_piItemDefaults [20]; g_wpiItemDefaults[20].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[20].vt = g_pvItemDefaults [20].vt; // Intialize WIA_IPA_PLANAR (NONE) g_pszItemDefaults[21] = WIA_IPA_PLANAR_STR; g_piItemDefaults [21] = WIA_IPA_PLANAR; g_pvItemDefaults [21].lVal = INITIAL_PLANAR; g_pvItemDefaults [21].vt = VT_I4; g_psItemDefaults [21].ulKind = PRSPEC_PROPID; g_psItemDefaults [21].propid = g_piItemDefaults [21]; g_wpiItemDefaults[21].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[21].vt = g_pvItemDefaults [21].vt; // Intialize WIA_IPA_BYTES_PER_LINE (NONE) g_pszItemDefaults[22] = WIA_IPA_BYTES_PER_LINE_STR; g_piItemDefaults [22] = WIA_IPA_BYTES_PER_LINE; g_pvItemDefaults [22].lVal = 0; g_pvItemDefaults [22].vt = VT_I4; g_psItemDefaults [22].ulKind = PRSPEC_PROPID; g_psItemDefaults [22].propid = g_piItemDefaults [22]; g_wpiItemDefaults[22].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[22].vt = g_pvItemDefaults [22].vt; // Intialize WIA_IPA_MIN_BUFFER_SIZE (NONE) g_pszItemDefaults[23] = WIA_IPA_MIN_BUFFER_SIZE_STR; g_piItemDefaults [23] = WIA_IPA_MIN_BUFFER_SIZE; g_pvItemDefaults [23].lVal = MIN_BUFFER_SIZE; g_pvItemDefaults [23].vt = VT_I4; g_psItemDefaults [23].ulKind = PRSPEC_PROPID; g_psItemDefaults [23].propid = g_piItemDefaults [23]; g_wpiItemDefaults[23].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[23].vt = g_pvItemDefaults [23].vt; // Intialize WIA_IPA_ACCESS_RIGHTS (NONE) g_pszItemDefaults[24] = WIA_IPA_ACCESS_RIGHTS_STR; g_piItemDefaults [24] = WIA_IPA_ACCESS_RIGHTS; g_pvItemDefaults [24].lVal = WIA_ITEM_READ|WIA_ITEM_WRITE; g_pvItemDefaults [24].vt = VT_UI4; g_psItemDefaults [24].ulKind = PRSPEC_PROPID; g_psItemDefaults [24].propid = g_piItemDefaults [24]; g_wpiItemDefaults[24].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[24].vt = g_pvItemDefaults [24].vt; // Intialize WIA_IPA_SENSITIVITY (RANGE) g_pszItemDefaults[25] = WIA_IPA_SENSITIVITY_STR; g_piItemDefaults [25] = WIA_IPA_SENSITIVITY; g_pvItemDefaults [25].fltVal = INITIAL_SENSITIVITY; g_pvItemDefaults [25].vt = VT_R4; g_psItemDefaults [25].ulKind = PRSPEC_PROPID; g_psItemDefaults [25].propid = g_piItemDefaults [25]; g_wpiItemDefaults[25].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[25].vt = g_pvItemDefaults [25].vt; g_wpiItemDefaults[25].ValidVal.RangeFloat.Inc = 1.0f; g_wpiItemDefaults[25].ValidVal.RangeFloat.Min = -10.0f; g_wpiItemDefaults[25].ValidVal.RangeFloat.Max = 10.0f; g_wpiItemDefaults[25].ValidVal.RangeFloat.Nom = g_pvItemDefaults [25].fltVal; // Intialize WIA_IPA_CORRECTION (RANGE) g_pszItemDefaults[26] = WIA_IPA_CORRECTION_STR; g_piItemDefaults [26] = WIA_IPA_CORRECTION; g_pvItemDefaults [26].fltVal = INITIAL_CORRECTION; g_pvItemDefaults [26].vt = VT_R4; g_psItemDefaults [26].ulKind = PRSPEC_PROPID; g_psItemDefaults [26].propid = g_piItemDefaults [26]; g_wpiItemDefaults[26].lAccessFlags = WIA_PROP_RW|WIA_PROP_RANGE; g_wpiItemDefaults[26].vt = g_pvItemDefaults [26].vt; g_wpiItemDefaults[26].ValidVal.RangeFloat.Inc = 1.0f; g_wpiItemDefaults[26].ValidVal.RangeFloat.Min = -500.0f; g_wpiItemDefaults[26].ValidVal.RangeFloat.Max = 500.0f; g_wpiItemDefaults[26].ValidVal.RangeFloat.Nom = g_pvItemDefaults [26].fltVal; // Intialize WIA_IPA_COMPRESSION (LIST) g_pszItemDefaults[27] = WIA_IPA_COMPRESSION_STR; g_piItemDefaults [27] = WIA_IPA_COMPRESSION; g_pvItemDefaults [27].lVal = INITIAL_COMPRESSION; g_pvItemDefaults [27].vt = VT_I4; g_psItemDefaults [27].ulKind = PRSPEC_PROPID; g_psItemDefaults [27].propid = g_piItemDefaults [27]; g_wpiItemDefaults[27].lAccessFlags = WIA_PROP_RW|WIA_PROP_LIST; g_wpiItemDefaults[27].vt = g_pvItemDefaults [27].vt; g_wpiItemDefaults[27].ValidVal.List.pList = (BYTE*)g_CompressionArray; g_wpiItemDefaults[27].ValidVal.List.Nom = g_pvItemDefaults [27].lVal; g_wpiItemDefaults[27].ValidVal.List.cNumList = NUM_COMPRESSIONS; // Initialize WIA_IPA_ITEM_FLAGS g_pszItemDefaults[28] = WIA_IPA_ITEM_FLAGS_STR; g_piItemDefaults [28] = WIA_IPA_ITEM_FLAGS; g_pvItemDefaults [28].lVal = WiaItemTypeImage|WiaItemTypeFile|WiaItemTypeDevice; g_pvItemDefaults [28].vt = VT_I4; g_psItemDefaults [28].ulKind = PRSPEC_PROPID; g_psItemDefaults [28].propid = g_piItemDefaults [28]; g_wpiItemDefaults[28].lAccessFlags = WIA_PROP_READ|WIA_PROP_FLAG; g_wpiItemDefaults[28].vt = g_pvItemDefaults [28].vt; g_wpiItemDefaults[28].ValidVal.Flag.Nom = g_pvItemDefaults [28].lVal; g_wpiItemDefaults[28].ValidVal.Flag.ValidBits = WiaItemTypeImage|WiaItemTypeFile|WiaItemTypeDevice; // Initialize WIA_IPS_PHOTOMETRIC_INTERP g_pszItemDefaults[29] = WIA_IPS_PHOTOMETRIC_INTERP_STR; g_piItemDefaults [29] = WIA_IPS_PHOTOMETRIC_INTERP; g_pvItemDefaults [29].lVal = INITIAL_PHOTOMETRIC_INTERP; g_pvItemDefaults [29].vt = VT_I4; g_psItemDefaults [29].ulKind = PRSPEC_PROPID; g_psItemDefaults [29].propid = g_piItemDefaults [29]; g_wpiItemDefaults[29].lAccessFlags = WIA_PROP_READ|WIA_PROP_NONE; g_wpiItemDefaults[29].vt = g_pvItemDefaults [29].vt; return hr; } /**************************************************************************\ * BuildCapabilities * * This helper initialize the global capabilities array * * Arguments: * * none * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::BuildCapabilities() { HRESULT hr = S_OK; if(g_bCapabilitiesInitialized) { // // Capabilities have already been initialized, // so return S_OK. // return hr; } // // Initialize EVENTS // // WIA_EVENT_DEVICE_CONNECTED GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_NAME,&(g_Capabilities[0].wszName),TRUE); GetOLESTRResourceString(IDS_EVENT_DEVICE_CONNECTED_DESC,&(g_Capabilities[0].wszDescription),TRUE); g_Capabilities[0].guid = (GUID*)&WIA_EVENT_DEVICE_CONNECTED; g_Capabilities[0].ulFlags = WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT; g_Capabilities[0].wszIcon = WIA_ICON_DEVICE_CONNECTED; // WIA_EVENT_DEVICE_DISCONNECTED GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_NAME,&(g_Capabilities[1].wszName),TRUE); GetOLESTRResourceString(IDS_EVENT_DEVICE_DISCONNECTED_DESC,&(g_Capabilities[1].wszDescription),TRUE); g_Capabilities[1].guid = (GUID*)&WIA_EVENT_DEVICE_DISCONNECTED; g_Capabilities[1].ulFlags = WIA_NOTIFICATION_EVENT; g_Capabilities[1].wszIcon = WIA_ICON_DEVICE_DISCONNECTED; // // Initialize COMMANDS // // WIA_CMD_SYNCHRONIZE GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_NAME,&(g_Capabilities[2].wszName),TRUE); GetOLESTRResourceString(IDS_CMD_SYNCRONIZE_DESC,&(g_Capabilities[2].wszDescription),TRUE); g_Capabilities[2].guid = (GUID*)&WIA_CMD_SYNCHRONIZE; g_Capabilities[2].ulFlags = 0; g_Capabilities[2].wszIcon = WIA_ICON_SYNCHRONIZE; // WIA_CMD_DELETE_ALL_ITEMS GetOLESTRResourceString(IDS_CMD_DELETE_ALL_ITEMS_NAME,&(g_Capabilities[3].wszName),TRUE); GetOLESTRResourceString(IDS_CMD_DELETE_ALL_ITEMS_DESC,&(g_Capabilities[3].wszDescription),TRUE); g_Capabilities[3].guid = (GUID*)&WIA_CMD_DELETE_ALL_ITEMS; g_Capabilities[3].ulFlags = 0; g_Capabilities[3].wszIcon = WIA_ICON_DELETE_ALL_ITEMS; // WIA_CMD_DELETE_DEVICE_TREE GetOLESTRResourceString(IDS_CMD_DELETE_DEVICE_TREE_NAME,&(g_Capabilities[4].wszName),TRUE); GetOLESTRResourceString(IDS_CMD_DELETE_DEVICE_TREE_DESC,&(g_Capabilities[4].wszDescription),TRUE); g_Capabilities[4].guid = (GUID*)&WIA_CMD_DELETE_DEVICE_TREE; g_Capabilities[4].ulFlags = 0; g_Capabilities[4].wszIcon = WIA_ICON_DELETE_DEVICE_TREE; // WIA_CMD_BUILD_DEVICE_TREE GetOLESTRResourceString(IDS_CMD_BUILD_DEVICE_TREE_NAME,&(g_Capabilities[5].wszName),TRUE); GetOLESTRResourceString(IDS_CMD_BUILD_DEVICE_TREE_DESC,&(g_Capabilities[5].wszDescription),TRUE); g_Capabilities[5].guid = (GUID*)&WIA_CMD_BUILD_DEVICE_TREE; g_Capabilities[5].ulFlags = 0; g_Capabilities[5].wszIcon = WIA_ICON_BUILD_DEVICE_TREE; g_bCapabilitiesInitialized = TRUE; return hr; } /**************************************************************************\ * DeleteCapabilitiesArrayContents * * This helper cleans up allocated strings used in the global capabilities array * * Arguments: * * none * * Return Value: * * Status * * History: * * 11/16/1999 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::DeleteCapabilitiesArrayContents() { HRESULT hr = S_OK; if(g_bCapabilitiesInitialized) { g_bCapabilitiesInitialized = FALSE; for (INT i = 0; i < NUM_CAPABILITIES;i++) { CoTaskMemFree(g_Capabilities[i].wszName); CoTaskMemFree(g_Capabilities[i].wszDescription); } } return hr; }