/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1998 * * TITLE: MiniItem.Cpp * * VERSION: 2.0 * * AUTHOR: marke * * DATE: 30 Aug, 1998 * * DESCRIPTION: * Implementation of the WIA test camera item methods. * *******************************************************************************/ #include #include #include #ifdef TEST_PER_USER_DATA #ifdef UNICODE #include #endif #endif #include "testusd.h" #include "defprop.h" extern HINSTANCE g_hInst; // Global hInstance /******************************************************************************* * * ValidateDataTransferContext * * DESCRIPTION: * Validate the data transfer context. * * PARAMETERS: * *******************************************************************************/ HRESULT ValidateDataTransferContext( PMINIDRV_TRANSFER_CONTEXT pDataTransferContext) { if (pDataTransferContext->lSize != sizeof(MINIDRV_TRANSFER_CONTEXT)) { WIAS_ERROR((g_hInst,"ValidateDataTransferContext, invalid data transfer context")); return E_INVALIDARG;; } // // for tymed file or hglobal, only WiaImgFmt_MEMORYBMP is allowed // if ((pDataTransferContext->tymed == TYMED_FILE) || (pDataTransferContext->tymed == TYMED_HGLOBAL)) { if (pDataTransferContext->guidFormatID != WiaImgFmt_BMP && pDataTransferContext->guidFormatID != WiaAudFmt_WAV) { WIAS_ERROR((g_hInst,"ValidateDataTransferContext, invalid format")); return E_INVALIDARG;; } } // // for tymed CALLBACK, only WiaImgFmt_MEMORYBMP is allowed // if (pDataTransferContext->tymed == TYMED_CALLBACK) { if ((pDataTransferContext->guidFormatID != WiaImgFmt_BMP) && (pDataTransferContext->guidFormatID != WiaImgFmt_MEMORYBMP)) { WIAS_ERROR((g_hInst,"AcquireDeviceData, invalid format")); return E_INVALIDARG;; } } // // callback is always double buffered, non-callback never is // if (pDataTransferContext->pTransferBuffer == NULL) { WIAS_ERROR((g_hInst, "AcquireDeviceData, invalid transfer buffer")); return E_INVALIDARG; } return S_OK; } /**************************************************************************\ * SendBitmapHeader * * * * Arguments: * * * * Return Value: * * Status * * History: * * 11/17/1998 Original Version * \**************************************************************************/ HRESULT SendBitmapHeader( IWiaDrvItem *pDrvItem, PMINIDRV_TRANSFER_CONTEXT pTranCtx) { HRESULT hr; WIAS_ASSERT(g_hInst, pDrvItem != NULL); WIAS_ASSERT(g_hInst, pTranCtx != NULL); WIAS_ASSERT(g_hInst, pTranCtx->tymed == TYMED_CALLBACK); // // driver is sending TOPDOWN data, must swap biHeight // // this routine assumes pTranCtx->pHeader points to a // BITMAPINFO header (TYMED_FILE doesn't use this path // and DIB is the only format supported now) // PBITMAPINFO pbmi = (PBITMAPINFO)pTranCtx->pTransferBuffer; if (pTranCtx->guidFormatID == WiaImgFmt_MEMORYBMP) { pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight; } hr = pTranCtx-> pIWiaMiniDrvCallBack-> MiniDrvCallback( IT_MSG_DATA, IT_STATUS_TRANSFER_TO_CLIENT, 0, 0, pTranCtx->lHeaderSize, pTranCtx, 0); if (hr == S_OK) { // // advance offset for destination copy // pTranCtx->cbOffset += pTranCtx->lHeaderSize; } return hr; } /**************************************************************************\ * TestUsdDevice::drvDeleteItem * * Try to delete a device item. Device items for the test scanner may * not be modified. * * Arguments: * * pWiasContext - The context of the item to delete * lFlags - unused * plDevErrVal - unused * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvDeleteItem( BYTE* pWiasContext, LONG lFlags, LONG* plDevErrVal) { *plDevErrVal = 0; return STG_E_ACCESSDENIED; } /**************************************************************************\ * TestUsdDevice::drvAcquireItemData * * Scan data into buffer. This routine scans the entire contents into * the destination buffer in one call. Status will be sent back if * the callback routine is provided * * Arguments: * * pWiasContext - identifies ITEM context * lFlags - unused * pTranCtx - buffer and callback information * plDevErrVal - error value * * Return Value: * * Status * * History: * * 11/17/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvAcquireItemData( BYTE *pWiasContext, LONG lFlags, PMINIDRV_TRANSFER_CONTEXT pTranCtx, LONG *plDevErrVal) { HRESULT hr; // #define TEST_PER_USER_DATA 1 #ifdef TEST_PER_USER_DATA #ifdef UNICODE BOOL bRet; TCHAR tszUserName[MAX_PATH]; DWORD dwBufSize; HANDLE hToken; PROFILEINFO profileInfo; LONG lRet; HKEY hKeyCurUser; #endif #endif *plDevErrVal = 0; // // How to access per user setting in the USD // #ifdef TEST_PER_USER_DATA #ifdef UNICODE #ifdef DEBUG dwBufSize = MAX_PATH; bRet = GetUserName(tszUserName, &dwBufSize); #endif #endif #endif #ifdef TEST_PER_USER_DATA #ifdef UNICODE hToken = NULL; __try { hr = CoImpersonateClient(); if (FAILED(hr)) { __leave; } #ifdef NEED_USER_PROFILE bRet = OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken); if (! bRet) { __leave; } // // Get the client's user name // dwBufSize = MAX_PATH; bRet = GetUserName(tszUserName, &dwBufSize); // // Revert to system account // hr = CoRevertToSelf(); if (FAILED(hr)) { __leave; } hr = S_FALSE; // // Load the user profile // ZeroMemory(&profileInfo, sizeof(profileInfo)); profileInfo.dwSize = sizeof(profileInfo); profileInfo.dwFlags = PI_NOUI; profileInfo.lpUserName = tszUserName; bRet = LoadUserProfile(hToken, &profileInfo); if (! bRet) { __leave; } // // Access user portion of the registry // // Use profileInfo.hProfile instead of HKEY_CURRENT_USER // // hKeyCurUser = (HKEY)profileInfo.hProfile; #else lRet = RegOpenCurrentUser(KEY_ALL_ACCESS, &hKeyCurUser); if (lRet != ERROR_SUCCESS) { __leave; } #endif HKEY hKeyEnv; lRet = RegOpenKey( hKeyCurUser, TEXT("Environment"), &hKeyEnv); if (lRet == ERROR_SUCCESS) { RegCloseKey(hKeyEnv); } } __finally { if (hr == S_OK) { CoRevertToSelf(); } #ifdef NEED_USER_PROFILE if (bRet) { UnloadUserProfile(hToken, profileInfo.hProfile); } if (hToken) { CloseHandle(hToken); } #else if (hKeyCurUser) { RegCloseKey(hKeyCurUser); } #endif } #endif #endif // // 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(pTranCtx); if (FAILED(hr)) { return hr; } // // get item specific driver data // MEMCAM_IMAGE_CONTEXT *pMCamContext; pDrvItem->GetDeviceSpecContext((BYTE **)&pMCamContext); if (!pMCamContext) { WIAS_ERROR((g_hInst,"drvAcquireItemData, NULL item context")); return E_POINTER; } // // Use WIA services to fetch format specific info. // if (!IsEqualGUID (pTranCtx->guidFormatID, WiaAudFmt_WAV) ) { hr = wiasGetImageInformation(pWiasContext, 0, pTranCtx); } else { WIN32_FILE_ATTRIBUTE_DATA wfd; GetFileAttributesEx (pMCamContext->pszCameraImagePath,GetFileExInfoStandard, &wfd); pTranCtx->lItemSize = (LONG)wfd.nFileSizeLow; } if (hr != S_OK) { return hr; } // // determine if this is a callback or buffered transfer // if (pTranCtx->tymed == TYMED_CALLBACK) { // // For formats that have a data header, send it to the client // if (pTranCtx->lHeaderSize > 0) { hr = SendBitmapHeader( pDrvItem, pTranCtx); } if (hr == S_OK) { hr = CamLoadPictureCB( pMCamContext, pTranCtx, plDevErrVal); } } else { // // inc past header // pTranCtx->cbOffset += pTranCtx->lHeaderSize; hr = CamLoadPicture( pMCamContext, pTranCtx, plDevErrVal); } return hr; } /**************************************************************************\ * TestUsdDevice::drvInitItemProperties * * Initialize the device item properties. * * Arguments: * * pWiasContext - Pointer to WIA item context. * lFLags - unused * plDevErrVal - pointer to hardware error value. * * * Return Value: * * Status * * History: * * 10/29/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvInitItemProperties( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr; LONG lItemType; PMEMCAM_IMAGE_CONTEXT pContext; // // This device doesn't touch hardware to initialize the // device item properties. // *plDevErrVal = 0; // // Parameter validation. // if (!pWiasContext) { WIAS_ERROR((g_hInst,"drvInitItemProperties, invalid input pointers")); return (E_INVALIDARG); } // // Get a pointer to the associated driver item. // IWiaDrvItem* pDrvItem; hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } // // Root item has the all the device properties // hr = pDrvItem->GetItemFlags(&lItemType); if (FAILED(hr)) { return (hr); } if (lItemType & WiaItemTypeRoot) { // Root item property init finishes here return (InitDeviceProperties(pWiasContext, plDevErrVal)); } // // If this is a file, init the properties // if (lItemType & WiaItemTypeImage) { // // Add the item property names. // hr = wiasSetItemPropNames(pWiasContext, NUM_CAM_ITEM_PROPS, gItemPropIDs, gItemPropNames); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvInitItemProperties, wiasSetItemPropNames() failed")); return (hr); } // // Use WIA services to set the defaul item properties. // hr = wiasWriteMultiple(pWiasContext, NUM_CAM_ITEM_PROPS, gPropSpecDefaults, (PROPVARIANT*)gPropVarDefaults); if (FAILED(hr)) { return (hr); } hr = pDrvItem->GetDeviceSpecContext((BYTE **)&pContext); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvInitItemProperties, GetDeviceSpecContext failed")); return (hr); } hr = InitImageInformation(pWiasContext, pContext, plDevErrVal); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvInitItemProperties InitImageInformation() failed")); return (hr); } } else if (lItemType & WiaItemTypeAudio) { // // Add the item property names. // hr = wiasSetItemPropNames(pWiasContext, NUM_AUDIO_PROPS, gAudioPropIDs, gAudioPropNames); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvInitItemProperties, wiasSetItemPropNames() failed")); return (hr); } // // Use WIA services to set the defaul item properties. // hr = wiasWriteMultiple(pWiasContext, NUM_AUDIO_PROPS, gAudioPropDefaults, (PROPVARIANT*)gAudioDefaults); if (FAILED(hr)) { return (hr); } hr = pDrvItem->GetDeviceSpecContext((BYTE **)&pContext); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvInitItemProperties, GetDeviceSpecContext failed")); return (hr); } hr = InitAudioInformation (pWiasContext, pContext, plDevErrVal); } return (S_OK); } /**************************************************************************\ * TestUsdDevice::drvValidateItemProperties * * Validate the device item properties. * * Arguments: * * pWiasContext - wia item context * lFlags - unused * nPropSpec - * pPropSpec - * plDevErrVal - 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) { // // This device doesn't touch hardware to validate the device item properties. // *plDevErrVal = 0; // // Parameter validation. // if (!pWiasContext || !pPropSpec) { WIAS_ERROR((g_hInst,"drvValidateItemProperties, invalid input pointers")); return E_POINTER; } // // validate size // HRESULT hr = S_OK; IWiaDrvItem* pDrvItem; hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } LONG lItemType; hr = pDrvItem->GetItemFlags(&lItemType); if (hr == S_OK) { if (lItemType & WiaItemTypeImage) { // // calc item size // hr = SetItemSize(pWiasContext); // // Change MinBufferSize property. Need to get Tymed and // ItemSize first, since MinBufferSize in dependant on these // properties. // LONG lTymed; LONG lItemSize; LONG lMinBufSize = 0; HRESULT hr = S_OK; hr = wiasReadPropLong(pWiasContext, WIA_IPA_TYMED, &lTymed, NULL, TRUE); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvValidateItemProperties, could not read TYMED property")); return hr; } hr = wiasReadPropLong(pWiasContext, WIA_IPA_ITEM_SIZE, &lItemSize, NULL, TRUE); if (SUCCEEDED(hr)) { // // Update the MinBufferSize property. // switch (lTymed) { case TYMED_CALLBACK: lMinBufSize = 65535; break; default: lMinBufSize = lItemSize; } if (lMinBufSize) { hr = wiasWritePropLong(pWiasContext, WIA_IPA_MIN_BUFFER_SIZE, lMinBufSize); if (FAILED(hr)) { WIAS_ERROR((g_hInst, "drvValidateItemProperties, could not write value for WIA_IPA_MIN_BUFFER_SIZE")); } } } else { WIAS_ERROR((g_hInst, "drvValidateItemProperties, could not read value for ItemSize")); } } else if (lItemType & WiaItemTypeRoot) { // // Find out whether the Root Path property is changed // for (ULONG i = 0; i < nPropSpec; i++) { if (((pPropSpec[i].ulKind == PRSPEC_PROPID) && (pPropSpec[i].propid == WIA_DPP_TCAM_ROOT_PATH)) || ((pPropSpec[i].ulKind == PRSPEC_LPWSTR) && (wcscmp(pPropSpec[i].lpwstr, WIA_DPP_TCAM_ROOT_PATH_STR) == 0))) { BSTR bstrRootPath; // // Retrieve the new value for Root Path property // hr = wiasReadPropStr( pWiasContext, WIA_DPP_TCAM_ROOT_PATH, &bstrRootPath, NULL, TRUE); if (FAILED(hr)) { return (hr); } #ifdef UNICODE wcscpy(gpszPath, bstrRootPath); #else wcstombs(gpszPath, bstrRootPath, MAX_PATH); #endif // // Release the Root Path bstr // SysFreeString(bstrRootPath); // // Rebuild the item tree and send event notification // hr = DeleteDeviceItemTree(plDevErrVal); if (FAILED(hr)) { break; } hr = BuildDeviceItemTree(plDevErrVal); if (FAILED(hr)) { break; } m_guidLastEvent = WIA_EVENT_DEVICE_CONNECTED; SetEvent(m_hSignalEvent); break; } } } } return (hr); } /**************************************************************************\ * TestUsdDevice::drvWriteItemProperties * * Write the device item properties to the hardware. * * Arguments: * * pWiasContext - the corresponding wia item context * pmdtc - pointer to mini driver context * pFlags - unused * plDevErrVal - 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) { // // Assume no device hardware errors. // *plDevErrVal = 0; // // Parameter validation. // if ((! pWiasContext) || (! pmdtc)) { WIAS_ERROR((g_hInst,"drvWriteItemProperties, invalid input pointers")); return E_POINTER; } // // Get a pointer to the associated driver item. // IWiaDrvItem* pDrvItem; HRESULT hr = wiasGetDrvItem(pWiasContext, &pDrvItem); if (FAILED(hr)) { return hr; } PMEMCAM_IMAGE_CONTEXT pItemContext; hr = pDrvItem->GetDeviceSpecContext((BYTE**)&pItemContext); if (FAILED(hr)) { WIAS_ERROR((g_hInst,"drvWriteItemProperties, NULL item context")); return E_POINTER; } // // Write the device item properties to the hardware here. // return hr; } /**************************************************************************\ * TestUsdDevice::drvReadItemProperties * * Read the device item properties from the hardware. * * Arguments: * * pWiasContext - wia item context * lFlags - unused * nPropSpec - * pPropSpec - * plDevErrVal - 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) { // 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. This can be done here. *plDevErrVal = 0; return S_OK; } /**************************************************************************\ * TestUsdDevice::drvLockWiaDevice * * Lock access to the device. * * Arguments: * * pWiasContext - unused, * lFlags - unused * plDevErrVal - device error value * * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::drvLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { *plDevErrVal = 0; if (m_pStiDevice) { return m_pStiDevice->LockDevice(100); } return S_OK; } /**************************************************************************\ * TestUsdDevice::drvUnLockWiaDevice * * Unlock access to the device. * * Arguments: * * pWiasContext - unused * lFlags - unused * plDevErrVal - device error value * * * Return Value: * * Status * * History: * * 9/11/1998 Original Version * \**************************************************************************/ HRESULT TestUsdDevice::drvUnLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { plDevErrVal = 0; return m_pStiDevice->UnLockDevice(); } /**************************************************************************\ * TestUsdDevice::drvAnalyzeItem * * The test camera does not support imag analysis. * * Arguments: * * pWiasContext - Pointer to the device item context to be analyzed. * lFlags - Operation flags. * plDevErrVal - device error value * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvAnalyzeItem( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { *plDevErrVal = 0; return E_NOTIMPL; } /**************************************************************************\ * TestUsdDevice::drvFreeDrvItemContext * * The test scanner does not support imag analysis. * * Arguments: * * lFlags - unused * pSpecContext - Pointer to item specific context. * plDevErrVal - device error value * * Return Value: * * Status * * History: * * 10/15/1998 Original Version * \**************************************************************************/ HRESULT _stdcall TestUsdDevice::drvFreeDrvItemContext( LONG lFlags, BYTE *pSpecContext, LONG *plDevErrVal) { PMEMCAM_IMAGE_CONTEXT pContext = (PMEMCAM_IMAGE_CONTEXT)pSpecContext; if (pContext != NULL) { if (pContext->pszCameraImagePath != NULL) { free(pContext->pszCameraImagePath); pContext->pszCameraImagePath = NULL; } } return S_OK; }