/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 2000 * * TITLE: drvwrap.cpp * * VERSION: 1.0 * * AUTHOR: ByronC * * DATE: 6 Nov, 2000 * * DESCRIPTION: * Declarations and definitions for the WIA driver wrapper class. * It faciliates JIT loading/unloading of drivers and provides an extra layer * of abstraction for WIA server components - they don't deal directly with * driver interfaces. This is to make us more robust and implement smart * driver handling. * *******************************************************************************/ #include "precomp.h" #include "stiexe.h" #include "lockmgr.h" /**************************************************************************\ * CDrvWrap::CDrvWrap * * Constructor for driver wrapper. * * Arguments: * * None. * * Return Value: * * None. * * History: * * 11/06/2000 Original Version * \**************************************************************************/ CDrvWrap::CDrvWrap() { m_hDriverDLL = NULL; m_hInternalMutex = NULL; m_pDeviceInfo = NULL; m_pUsdIUnknown = NULL; m_pIStiUSD = NULL; m_pIWiaMiniDrv = NULL; m_pIStiDeviceControl = NULL; m_bJITLoading = FALSE; m_lWiaTreeCount = 0; m_bPreparedForUse = FALSE; m_bUnload = FALSE; } /**************************************************************************\ * CDrvWrap::~CDrvWrap * * Desctructor for driver wrapper. Calls internal clear to make sure * driver is unloaded if it hasn't been already. Releases any * resources help by the wrapper that needs to live accross driver * loading/unloading, such as the DEVICE_INFO * * Arguments: * * None. * * Return Value: * * None. * * History: * * 11/06/2000 Original Version * \**************************************************************************/ CDrvWrap::~CDrvWrap() { // // Release driver interfaces and unload driver // InternalClear(); if (m_hInternalMutex) { CloseHandle(m_hInternalMutex); m_hInternalMutex = NULL; } if (m_pDeviceInfo) { DestroyDevInfo(m_pDeviceInfo); m_pDeviceInfo = NULL; } } /**************************************************************************\ * CDrvWrap::Initialize * * Initializes any object members that could not be set in the constructor, * such as allocating resources that may fail. * * Arguments: * * None. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT CDrvWrap::Initialize() { HRESULT hr = E_FAIL; m_hInternalMutex = CreateMutex(NULL, FALSE, NULL); m_pDeviceInfo = (DEVICE_INFO*) LocalAlloc(LPTR, sizeof(DEVICE_INFO)); if (!m_hInternalMutex || !m_pDeviceInfo) { DBG_ERR(("CDrvWrap::Initialize, out of memory!")); hr = E_OUTOFMEMORY; } else { hr = S_OK; } if (FAILED(hr)) { if (m_hInternalMutex) { CloseHandle(m_hInternalMutex); m_hInternalMutex = NULL; } if (m_pDeviceInfo) { LocalFree(m_pDeviceInfo); m_pDeviceInfo = NULL; } } return hr; } /**************************************************************************\ * CDrvWrap::QueryInterface * * This QI will return it's own "this" pointer for IUnknown, but will * delegate down to the USD for any other interface. * * Arguments: * * iid - The interface ID of the requested interface. * ppv - Pointer to variable receiving the interface pointer. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT _stdcall CDrvWrap::QueryInterface(const IID& iid, void** ppv) { HRESULT hr = E_NOINTERFACE; // // Always delegate down to USD, unless asking for IUnknown // if (iid == IID_IUnknown) { *ppv = (IUnknown*) this; AddRef(); hr = S_OK; } else { if (PrepForUse(FALSE)) { if (m_pUsdIUnknown) { hr = m_pUsdIUnknown->QueryInterface(iid, ppv); } else { DBG_TRC(("CDrvWrap::QueryInterface, m_pUsdIUnknown == NULL")) } } else { DBG_WRN(("CDrvWrap::QueryInterface, attempting to call IStiUSD::QueryInterface when driver is not loaded")); } } return hr; } /**************************************************************************\ * CDrvWrap::AddRef * * Notice that this method simply returns 2. We don't want to subject the * lifetime of this object to ref-counting. * * Arguments: * * None. * * Return Value: * * 2 * * History: * * 11/06/2000 Original Version * \**************************************************************************/ ULONG _stdcall CDrvWrap::AddRef(void) { ULONG ulCount = 2; // // Since we plan to manually load/unload the driver, we don't really want // to honor any AddRef/Release calls. // return ulCount; } /**************************************************************************\ * CDrvWrap::Release * * Notice that this method simply returns 1. We don't want to subject the * lifetime of this object to ref-counting. * * Arguments: * * * * Return Value: * * 1 * * History: * * 11/06/2000 Original Version * \**************************************************************************/ ULONG _stdcall CDrvWrap::Release(void) { ULONG ulCount = 1; // // We don't want this object to be controlled with refcounting - the // DEVICE_OBJECT will manually delete us when it's done. Also, since // we want to manually load/unload the driver, we don't really want // to honor any AddRef/Release calls down to it.. // return ulCount; } /**************************************************************************\ * CDrvWrap::LoadInitDriver * * Load the USD and initialize it appropriately. * * Arguments: * * hKeyDeviceParams - The device registry key. This is handed down to the * driver during intialization. If it is NULL, we will * attempt to find the real one to hand down to the * driver. For volume devices, there is no registry * key and NULL will be handed down. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT CDrvWrap::LoadInitDriver(HKEY hKeyDeviceParams) { HRESULT hr = E_UNEXPECTED; IUnknown *pThisUnk = NULL; BOOL bOpenedKey = FALSE; if (!m_pDeviceInfo) { DBG_WRN(("CDrvWrap::LoadInitDriver, can't load driver with no Device Information")); return hr; } if (!m_pDeviceInfo->bValid) { DBG_WRN(("CDrvWrap::LoadInitDriver, called with invalid Device Information")); return hr; } // // Create a new IStiDeviceControl object. This needs to be handed down to the // driver during initialization. If we can't create it, then bail, since we // wont be able to initialize the driver properly. // hr = CreateDeviceControl(); if (FAILED(hr)) { DBG_WRN(("CDrvWrap::LoadInitDriver, could not create IStiDeviceControl object. Aborting driver loading")); return hr; } // // If the hKeyDeviceParams is NULL, see if it is a real WIA device. If not, then // it is supposed to be NULL, else see if we can get it from our DevMan, using // this device's DevInfoData. // if ((hKeyDeviceParams == NULL) && (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_REAL)) { // // Check whether device is interface or devnode type device. Grab the // HKey from the appropriate place // hKeyDeviceParams = g_pDevMan->GetDeviceHKey(m_pDeviceInfo->wszDeviceInternalName, NULL); bOpenedKey = TRUE; } // // We always create the USD object as aggregated, so first we get our IUnknown // pointer to pass it it during CoCreate. // hr = QueryInterface(IID_IUnknown, (void**) &pThisUnk); if (SUCCEEDED(hr)) { // // Call our own version of CoCreate. This is to facilitate manual loading/unloading // of drivers. // hr = MyCoCreateInstanceW(m_pDeviceInfo->wszUSDClassId, pThisUnk, IID_IUnknown, (PPV) &m_pUsdIUnknown, &m_hDriverDLL); if (SUCCEEDED(hr)) { // // QI for the IStiUSD interface. Notice that we can call our own // QueryInterface since it delegates down to the driver via m_pUsdIUnknown. // hr = m_pUsdIUnknown->QueryInterface(IID_IStiUSD, (void**) &m_pIStiUSD); if (SUCCEEDED(hr)) { // // If this is a WIA device, QI for IWiaMiniDrv // if (IsWiaDevice()) { hr = m_pUsdIUnknown->QueryInterface(IID_IWiaMiniDrv, (void**) &m_pIWiaMiniDrv); if (FAILED(hr)) { DBG_WRN(("CDrvWrap::LoadInitDriver, WIA driver did not return IWiaMiniDrv interface for device (%ws)", getDeviceId())); // // Change hr here to indicate success. Even if WIA portoin of driver // doesn't work, the STI portion does so far. Any WIA calls down to this // driver will result in a E_NOINTERFACE error returned by the wrapper. // hr = S_OK; } } // // We now have the Sti USD, so let's initialize it // hr = STI_Initialize(m_pIStiDeviceControl, STI_VERSION_REAL, hKeyDeviceParams); if (SUCCEEDED(hr)) { // // Now get capabilities of the USD and verify version // STI_USD_CAPS DeviceCapabilities; hr = STI_GetCapabilities(&DeviceCapabilities); if (SUCCEEDED(hr)) { if (STI_VERSION_MIN_ALLOWED <= DeviceCapabilities.dwVersion) { // // Everything's fine, we've loaded the USD. Do any post // initialization steps e.g. for MSC devices, make sure // we tell the driver what drive/mount point is should // be attached to. // } else { // // Driver version is too old, driver will probably not work, so unload it. // DBG_WRN(("CDrvWrap::LoadInitDriver, driver version is incompatible (too old)")); hr = STIERR_OLD_VERSION; } } else { DBG_WRN(("CDrvWrap::LoadInitDriver, STI_GetCapabilities failed")); } } else { DBG_WRN(("CDrvWrap::LoadInitDriver, STI_Initialize failed")); } } else { DBG_WRN(("CDrvWrap::LoadInitDriver, QI to driver failed to return IStiUSD")); } } else { DBG_WRN(("CDrvWrap::LoadInitDriver, failed to CoCreate driver, hr = 0x%08X", hr)); } // // If anything failed, call UnloadDriver to clean up. // if (FAILED(hr)) { DBG_WRN(("CDrvWrap::LoadInitDriver, Aborting driver loading")); pThisUnk->Release(); UnLoadDriver(); } } else { DBG_ERR(("CDrvWrap::LoadInitDriver, could not get this IUnknown to hand to driver for aggregation")); } // // If we had to open the key, make sure we close it. We don't want to close the key // if it was handed to us. // if(hKeyDeviceParams && bOpenedKey) RegCloseKey(hKeyDeviceParams); return hr; } /**************************************************************************\ * CDrvWrap::UnLoadDriver * * This method will unload the driver. NOTE assumption: This method * assumes all WIA item references have already been released when this * is called. The reason is that drvUnInitializeWia needs to be called for * each WIA Item tree. * TBD: * One possible way to get around this is: Keep a list of WIA items * attached to this device. Then, if we get here, call drvUnitializeWia, * passing the root of each item tree. Another, much better way: store * the driver item tree in the wrapper. Then destroy the tree either when * asked, or when unloading the driver. * * Arguments: * * None. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT CDrvWrap::UnLoadDriver() { HRESULT hr = E_UNEXPECTED; // // Release all driver interfaces we're holding // if (m_pIWiaMiniDrv) { m_pIWiaMiniDrv->Release(); m_pIWiaMiniDrv = NULL; } if (m_pIStiUSD) { m_pIStiUSD->Release(); m_pIStiUSD = NULL; } if (m_pUsdIUnknown) { m_pUsdIUnknown->Release(); m_pUsdIUnknown = NULL; } // // Release the device control object // if (m_pIStiDeviceControl) { m_pIStiDeviceControl->Release(); m_pIStiDeviceControl = NULL; } // // Unload the driver DLL. We load/unload the DLL manually to ensure the driver // DLL is released when requested e.g. when the user wants to update the driver. // if (m_hDriverDLL) { FreeLibrary(m_hDriverDLL); m_hDriverDLL = NULL; } m_lWiaTreeCount = 0; m_bPreparedForUse = FALSE; m_bUnload = FALSE; // // Notice that we don't clear m_pDeviceInfo. This information is needed if we // decide to reload the driver. // return hr; } /**************************************************************************\ * CDrvWrap::IsValid * * This object is considered valid if there is nothing preventing it from * loading the driver. * * Arguments: * * None. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsValid() { // // This object is considered valid if there is nothing preventing // it from loading the driver. // We should be able to load the driver if: // - We have a non-NULL DeviceInfo struct // - The DeviceInfo struct contains valid data // - The device is marked as active // if (m_pDeviceInfo) { if (m_pDeviceInfo->bValid && (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE)) { return TRUE; } } return FALSE; } /**************************************************************************\ * CDrvWrap::IsDriverLoaded * * Checks whether driver is loaded * * Arguments: * * None. * * Return Value: * * True - driver is loaded * False - driver is not loaded * * History: * * 11/06/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsDriverLoaded() { HRESULT hr = E_UNEXPECTED; // // We know driver is loaded if we have a valid interface pointer to it. // if (m_pUsdIUnknown) { return TRUE; } return FALSE; } /**************************************************************************\ * CDrvWrap::IsWiaDevice * * This method looks at the capabilities to decide whether a driver is * WIA capable or not. * * Arguments: * * None. * * Return Value: * * TRUE - Is a WIA device * FALSE - Not a WIA device * * History: * * 11/06/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsWiaDevice() { if (m_pDeviceInfo) { // // Drivers report that they're WIA capable in their STI capabilties // entry. // return (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_WIA); } // // If we don't know for sure it's a WIA device, then assume it isn't // return FALSE; } /**************************************************************************\ * CDrvWrap::IsWiaDriverLoaded * * This method looks at the IWIaMiniDrv interface pointer from the driver * and returns whether it is valid or not. * * Arguments: * * None. * * Return Value: * * TRUE - WIA portion of driver is loaded * FALSE - WIA portion of driver is not loaded * * History: * * 12/15/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsWiaDriverLoaded() { if (m_pIWiaMiniDrv) { // // If this interface is non-NULL, it means we successfully QI'd // for it during initialization. Therefore the driver is loaded // and is WIA capable. // return TRUE; } return FALSE; } /**************************************************************************\ * CDrvWrap::IsPlugged * * Checks the DEVICE_INFO to see whether the device has been marked as * active. Devies on a PnP bus like USB are inactive if not plugged in. * * Arguments: * * None. * * Return Value: * * TRUE - Device is active, and is considered plugged * FALSE - Device is inactive, and is not considered to be plugged in. * * History: * * 11/06/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsPlugged() { if (m_pDeviceInfo) { // // Check the device state // return (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE); } // // If we don't know for sure it's plugged in, then assume it isn't // return FALSE; } /**************************************************************************\ * CDrvWrap::IsVolumeDevice * * Checks the DEVICE_INFO to see whether the device is marked as a volume * device. * * Arguments: * * None. * * Return Value: * * TRUE - Device is a volume device * FALSE - Device is not a volume device * * History: * * 12/13/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::IsVolumeDevice() { if (m_pDeviceInfo) { // // Check the device internal type // return (m_pDeviceInfo->dwInternalType & INTERNAL_DEV_TYPE_VOL); } // // If we don't know for sure it's a volume device, then assume it isn't // return FALSE; } /**************************************************************************\ * CDrvWrap::PrepForUse * * This method is generally called just before making a call down to the * driver. It checks to see whether the driver is loaded, and if it isn't, * will attempt to load it. * * Arguments: * * bForWiaCall - Indicates whether this is being called because a WIA * call is about to be made. This will check that the * IWiaMiniDrv interface is valid. * pRootItem - not used * * Return Value: * * TRUE - Device is ready to be used * FALSE - Device cannot be used (driver could not be loaded/initialized) * * History: * * 11/06/2000 Original Version * \**************************************************************************/ BOOL CDrvWrap::PrepForUse(BOOL bForWiaCall, IWiaItem *pRootItem) { HRESULT hr = S_OK; if (!m_bPreparedForUse || (bForWiaCall && !m_pIWiaMiniDrv)) { // // Only attempt to load if the device is marked as ACTIVE // if (m_pDeviceInfo->dwDeviceState & DEV_STATE_ACTIVE) { if (!IsDriverLoaded()) { hr = LoadInitDriver(); } if (SUCCEEDED(hr)) { if (m_pDeviceInfo) { if (bForWiaCall) { // // For WIA devices, check that we have a valid IWiaMiniDrv interface // if (IsWiaDevice()) { if (!m_pIWiaMiniDrv) { // // Attempt to Q.I. for IWiaMiniDrv again. // hr = m_pUsdIUnknown->QueryInterface(IID_IWiaMiniDrv, (VOID**) &m_pIWiaMiniDrv); if (FAILED(hr) || !m_pIWiaMiniDrv) { DBG_WRN(("CDrvWrap::PrepForUse, attempting to use WIA driver which doesn't have IWiaMiniDrv interface")); hr = E_NOINTERFACE; } } } } } else { DBG_WRN(("CDrvWrap::PrepForUse, attempting to use driver with NULL DeviceInfo")); hr = E_UNEXPECTED; } if (SUCCEEDED(hr)) { m_bPreparedForUse = TRUE; } } else { DBG_ERR(("CDrvWrap::PrepForUse, LoadInitDriver() failed (%x)", hr)); } } } if (!m_bPreparedForUse) { DBG_TRC(("CDrvWrap::PrepForUse, Driver could NOT be loaded!")); } return m_bPreparedForUse; } /*****************************************************************************/ // // Accessor methods // WCHAR* CDrvWrap::getPnPId() { if (m_pDeviceInfo) { //TBD: //return m_pDeviceInfo->wszPnPId; } return NULL; } WCHAR* CDrvWrap::getDeviceId() { if (m_pDeviceInfo) { return m_pDeviceInfo->wszDeviceInternalName; } return NULL; } DWORD CDrvWrap::getLockHoldingTime() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwLockHoldingTime; } return 0; } DWORD CDrvWrap::getGenericCaps() { if (m_pDeviceInfo) { return m_pDeviceInfo->DeviceCapabilities.dwGenericCaps; } return 0; } DWORD CDrvWrap::getPollTimeout() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwPollTimeout; } return 0; } DWORD CDrvWrap::getDisableNotificationsValue() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwDisableNotifications; } return 0; } DWORD CDrvWrap::getHWConfig() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwHardwareConfiguration; } return 0; } DWORD CDrvWrap::getDeviceState() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwDeviceState; } return 0; } HRESULT CDrvWrap::setDeviceState( DWORD dwNewDevState) { if (m_pDeviceInfo) { m_pDeviceInfo->dwDeviceState = dwNewDevState; return S_OK; } DBG_WRN(("CDrvWrap::setDeviceState, attempting to set device state when DeviceInfo is NULL")); return E_UNEXPECTED; } DEVICE_INFO* CDrvWrap::getDevInfo() { return m_pDeviceInfo; } HRESULT CDrvWrap::setDevInfo(DEVICE_INFO *pInfo) { HRESULT hr = E_UNEXPECTED; if (pInfo) { // // Caller allocates pInfo. We release it when we're done. // DeviceInfo must be set before driver can be loaded. // m_pDeviceInfo = pInfo; } else { DBG_ERR(("CDrvWrap::setDevInfo, attempting to set DeviceInfo to invalid value (NULL)")); } return hr; } ULONG CDrvWrap::getInternalType() { if (m_pDeviceInfo) { return m_pDeviceInfo->dwInternalType; } return 0; } VOID CDrvWrap::setJITLoading(BOOL bJITLoading) { m_bJITLoading = bJITLoading; } BOOL CDrvWrap::getJITLoading() { return m_bJITLoading; } LONG CDrvWrap::getWiaClientCount() { return m_lWiaTreeCount; } BOOL CDrvWrap::wasConnectEventThrown() { if (m_pDeviceInfo) { return (m_pDeviceInfo->dwDeviceState & DEV_STATE_CON_EVENT_WAS_THROWN); } return FALSE; } VOID CDrvWrap::setConnectEventState( BOOL bEventState) { if (m_pDeviceInfo) { if (bEventState) { // // Set the bit to indicate that connect event was thrown // m_pDeviceInfo->dwDeviceState = (m_pDeviceInfo->dwDeviceState | DEV_STATE_CON_EVENT_WAS_THROWN); } else { // // Clear the bit that indicated the connect event was thrown // m_pDeviceInfo->dwDeviceState = (m_pDeviceInfo->dwDeviceState & (~DEV_STATE_CON_EVENT_WAS_THROWN)); } } } // // End of accessor methods // /*****************************************************************************/ /*****************************************************************************/ // // Wrapper methods for IStiUSD // HRESULT CDrvWrap::STI_Initialize( IStiDeviceControl *pHelDcb, DWORD dwStiVersion, HKEY hParametersKey) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Initialize USD object // __try { hr = m_pIStiUSD->Initialize(pHelDcb, dwStiVersion, hParametersKey); } __except(EXCEPTION_EXECUTE_HANDLER ) { DBG_WRN(("CDrvWrap::STI_Initialize, exception in driver calling IStiUSD::Initialize")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_Initialize, attempting to call IStiUSD::Initialize when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_GetCapabilities(STI_USD_CAPS *pDevCaps) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Get STI capabilities from USD object // __try { hr = m_pIStiUSD->GetCapabilities(pDevCaps); } __except(EXCEPTION_EXECUTE_HANDLER ) { DBG_WRN(("CDrvWrap::STI_GetCapabilities, exception in driver calling IStiUSD::GetCapabilities")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_GetCapabilities, attempting to call IStiUSD::GetCapabilities when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_GetStatus( STI_DEVICE_STATUS *pDevStatus) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Get status from USD object // __try { hr = m_pIStiUSD->GetStatus(pDevStatus); } __except(EXCEPTION_EXECUTE_HANDLER ) { DBG_WRN(("CDrvWrap::STI_GetStatus, exception in driver calling IStiUSD::GetStatus")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_GetStatus, attempting to call IStiUSD::GetStatus when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_GetNotificationData( STINOTIFY *lpNotify) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Get event data from USD object // __try { hr = m_pIStiUSD->GetNotificationData(lpNotify); } __except(EXCEPTION_EXECUTE_HANDLER ) { DBG_WRN(("CDrvWrap::STI_GetNotificationData, exception in driver calling IStiUSD::GetNotificationData")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_GetNotificationData, attempting to call IStiUSD::GetNotificationData when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_SetNotificationHandle( HANDLE hEvent) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Set notification handle for USD object // __try { hr = m_pIStiUSD->SetNotificationHandle(hEvent); } __except(EXCEPTION_EXECUTE_HANDLER ) { DBG_WRN(("CDrvWrap::STI_SetNotificationHandle, exception in driver calling IStiUSD::SetNotificationHandle")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_SetNotificationHandle, attempting to call IStiUSD::SetNotificationHandle when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_DeviceReset() { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { // // Get status from USD object // __try { hr = m_pIStiUSD->DeviceReset(); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::STI_DeviceReset, driver returned failure with hr = 0x%08X", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::STI_DeviceReset, exception in driver calling IStiUSD::DeviceReset")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_DeviceReset, attempting to call IStiUSD::DeviceReset when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_Diagnostic( STI_DIAG *pDiag) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { __try { hr = m_pIStiUSD->Diagnostic(pDiag); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::STI_Diagnostic, driver returned failure with hr = 0x%08X", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::STI_Diagnostic, exception in Diagnostic: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_Diagnostic, attempting to call IStiUSD::Diagnostic when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_LockDevice() { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { __try { hr = m_pIStiUSD->LockDevice(); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::STI_LockDevice, driver returned failure with hr = 0x%08X", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::STI_LockDevice, exception in LockDevice: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_LockDevice, attempting to call IStiUSD::LockDevice when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_UnLockDevice() { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { __try { hr = m_pIStiUSD->UnLockDevice(); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::STI_UnLockDevice, driver returned failure with hr = 0x%08X", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::STI_UnLockDevice, exception in UnLockDevice: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_UnlockDevice, attempting to call IStiUSD::UnLockDevice when driver is not loaded")); } return hr; } HRESULT CDrvWrap::STI_Escape( STI_RAW_CONTROL_CODE EscapeFunction, LPVOID lpInData, DWORD cbInDataSize, LPVOID pOutData, DWORD dwOutDataSize, LPDWORD pdwActualData) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(FALSE)) { __try { hr = m_pIStiUSD->Escape(EscapeFunction, lpInData, cbInDataSize, pOutData, dwOutDataSize, pdwActualData); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::STI_Escape, driver returned failure with hr = 0x%08X", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::STI_Escape, exception in Escape: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::STI_Escape, attempting to call IStiUSD::Escape when driver is not loaded")); } return hr; } // // End of IStiUSD wrapper methods // /*****************************************************************************/ /*****************************************************************************/ // // Wrapper methods for IWiaMiniDrv. All mini-driver wrapper methods call PrepForUse(...) to make sure // the driver is loaded before using. // HRESULT CDrvWrap::WIA_drvInitializeWia( BYTE *pWiasContext, LONG lFlags, BSTR bstrDeviceID, BSTR bstrRootFullItemName, IUnknown *pStiDevice, IUnknown *pIUnknownOuter, IWiaDrvItem **ppIDrvItemRoot, IUnknown **ppIUnknownInner, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvInitializeWia(pWiasContext, lFlags, bstrDeviceID, bstrRootFullItemName, pStiDevice, pIUnknownOuter, ppIDrvItemRoot, ppIUnknownInner, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvInitializeWia, Error calling driver: drvInitializeWia failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvInitializeWia, exception in drvInitializeWia: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvInitializeWia, attempting to call IWiaMiniDrv::drvInitializeWia when driver is not loaded")); } if (SUCCEEDED(hr)) { // TBD: Take a sync primitive? InterlockedIncrement(&m_lWiaTreeCount); } return hr; } HRESULT CDrvWrap::WIA_drvGetDeviceErrorStr( LONG lFlags, LONG lDevErr, LPOLESTR *ppszDevErrStr, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvGetDeviceErrorStr(lFlags, lDevErr, ppszDevErrStr, plDevErrVal); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvGetDeviceErrorStr, call to driver's drvGetDeviceErrorStr failed (0x%08X)", hr)); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvGetDeviceErrorStr, attempting to call IWiaMiniDrv::drvGetDeviceErrorStr when driver is not loaded")); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } return hr; } HRESULT CDrvWrap::WIA_drvDeviceCommand( BYTE *pWiasContext, LONG lFlags, const GUID *plCommand, IWiaDrvItem **ppWiaDrvItem, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvDeviceCommand(pWiasContext, lFlags, plCommand, ppWiaDrvItem, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvDeviceCommand, Error calling driver: drvDeviceCommand failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvDeviceCommand, exception in drvDeviceCommand: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvDeviceCommand, attempting to call IWiaMiniDrv::drvDeviceCommand when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvAcquireItemData( BYTE *pWiasContext, LONG lFlags, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvAcquireItemData(pWiasContext, lFlags, pmdtc, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvAcquireItemData, Error calling driver : drvAcquireItemData failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvAcquireItemData, exception in drvAcquireItemData: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvAcquireItemData, attempting to call IWiaMiniDrv::drvAcquireItemData when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvInitItemProperties( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvInitItemProperties(pWiasContext,lFlags, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvInitItemProperties, Error calling driver: drvInitItemProperties failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvInitItemProperties, exception in drvInitItemProperties: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvInitItemProperties, attempting to call IWiaMiniDrv::drvInitItemProperties when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvValidateItemProperties( BYTE *pWiasContext, LONG lFlags, ULONG nPropSpec, const PROPSPEC *pPropSpec, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvValidateItemProperties(pWiasContext, lFlags, nPropSpec, pPropSpec, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvValidateItemProperties, Error calling driver: drvValidateItemProperties with hr = 0x%08X (This is normal if the app wrote an invalid value)", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvValidateItemProperties, exception in drvValidateItemProperties: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvValidateItemProperties, attempting to call IWiaMiniDrv::drvValidateItemProperties when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvWriteItemProperties( BYTE *pWiasContext, LONG lFlags, PMINIDRV_TRANSFER_CONTEXT pmdtc, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvWriteItemProperties(pWiasContext, lFlags, pmdtc, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvWriteItemProperties, error calling driver: drvWriteItemProperties failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvWriteItemProperties, exception in drvWriteItemProperties: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvWriteItemProperties, attempting to call IWiaMiniDrv::drvWriteItemProperties when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvReadItemProperties( BYTE *pWiasContext, LONG lFlags, ULONG nPropSpec, const PROPSPEC *pPropSpec, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvReadItemProperties(pWiasContext, lFlags, nPropSpec, pPropSpec, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvReadItemProperties, Error calling driver: drvReadItemProperties failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvReadItemProperties, exception in drvReadItemProperties: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvReadItemProperties, attempting to call IWiaMiniDrv::drvReadItemProperties when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { // // We request a lock on the device here. This is to ensure we don't // make calls down to the driver, which then turns around and // makes a call to us e.g. via the Fake Sti Device. // We no longer require driver to use the Fake Sti Device for // mutally exclusive locking - this way we do it automatically. // hr = g_pStiLockMgr->RequestLock(((CWiaItem*) pWiasContext)->m_pActiveDevice, WIA_LOCK_WAIT_TIME); if (SUCCEEDED(hr)) { __try { hr = m_pIWiaMiniDrv->drvLockWiaDevice(pWiasContext, lFlags, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvLockWiaDevice, driver returned failure with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvLockWiaDevice, exception in drvLockWiaDevice: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvLockWiaDevice, could not get device lock")); } } else { DBG_WRN(("CDrvWrap::WIA_drvLockWiaDevice, attempting to call IWiaMiniDrv::drvLockWiaDevice when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvUnLockWiaDevice( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; // // Note that we only want to call if the driver is loaded, therefore we don't // call PrepForUse. PrepForUse will attempt to load the driver if it wasn't // already loaded. // if (IsDriverLoaded()) { // // Request to unlock the device for mutally exclusive access. // Ignore the return, we must still call the drvUnlockWiaDevice entry // point. // __try { hr = m_pIWiaMiniDrv->drvUnLockWiaDevice(pWiasContext, lFlags, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvUnLockWiaDevice, driver returned failure with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvUnLockWiaDevice, exception in drvUnLockWiaDevice: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } hr = g_pStiLockMgr->RequestUnlock(((CWiaItem*) pWiasContext)->m_pActiveDevice); if (SUCCEEDED(hr) && m_bUnload) { UnLoadDriver(); } } else { DBG_WRN(("CDrvWrap::WIA_drvUnLockWiaDevice, attempting to call IWiaMiniDrv::drvUnLockWiaDevice when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvAnalyzeItem( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvAnalyzeItem(pWiasContext, lFlags, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvAnalyzeItem, Error calling driver: drvAnalyzeItem failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvAnalyzeItem, exception in drvAnalyzeItem: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvAnalyzeItem, attempting to call IWiaMiniDrv::drvAnalyzeItem when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvDeleteItem( BYTE *pWiasContext, LONG lFlags, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvDeleteItem(pWiasContext, lFlags, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvDeleteItem, Error calling driver: drvDeleteItem failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR( ("CDrvWrap::WIA_drvDeleteItem, exception in drvDeleteItem: %0xX", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvDeleteItem, attempting to call IWiaMiniDrv::drvDeleteItem when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvFreeDrvItemContext( LONG lFlags, BYTE *pSpecContext, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvFreeDrvItemContext(lFlags, pSpecContext, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvFreeDrvItemContext, Error calling driver: drvFreeDrvItemContext failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR( ("CDrvWrap::WIA_drvFreeDrvItemContext, exception in drvFreeDrvItemContext: %0xX", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvFreeDrvItemContext, attempting to call IWiaMiniDrv::drvFreeDrvItemContext when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvGetCapabilities( BYTE *pWiasContext, LONG ulFlags, LONG *pcelt, WIA_DEV_CAP_DRV **ppCapabilities, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvGetCapabilities(pWiasContext, ulFlags, pcelt, ppCapabilities, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvGetCapabilities, driver returned failure with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvGetCapabilities, exception in drvGetCapabilities: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvGetCapabilities, attempting to call IWiaMiniDrv::drvGetCapabilities when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvGetWiaFormatInfo( BYTE *pWiasContext, LONG lFlags, LONG *pcelt, WIA_FORMAT_INFO **ppwfi, LONG *plDevErrVal) { HRESULT hr = WIA_ERROR_OFFLINE; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvGetWiaFormatInfo(pWiasContext, lFlags, pcelt, ppwfi, plDevErrVal); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvGetWiaFormatInfo, Error calling driver : drvGetWiaFormatInfo failed with hr = 0x%08X", hr)); ReportMiniDriverError(*plDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR( ("CDrvWrap::WIA_drvGetWiaFormatInfo, exception in drvGetWiaFormatInfo: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvGetWiaFormatInfo, attempting to call IWiaMiniDrv::drvGetWiaFormatInfo when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvNotifyPnpEvent( const GUID *pEventGUID, BSTR bstrDeviceID, ULONG ulReserved) { HRESULT hr = WIA_ERROR_OFFLINE; LONG lDevErrVal = 0; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvNotifyPnpEvent(pEventGUID, bstrDeviceID, ulReserved); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvNotifyPnpEvent, driver returned failure with hr = 0x%08X", hr)); ReportMiniDriverError(lDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvNotifyPnpEvent, exception in drvNotifyPnpEvent: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvNotifyPnpEvent, attempting to call IWiaMiniDrv::drvNotifyPnpEvent when driver is not loaded")); } return hr; } HRESULT CDrvWrap::WIA_drvUnInitializeWia( BYTE *pWiasContext) { HRESULT hr = WIA_ERROR_OFFLINE; LONG lDevErrVal = 0; if (PrepForUse(TRUE)) { __try { hr = m_pIWiaMiniDrv->drvUnInitializeWia(pWiasContext); if(FAILED(hr)) { DBG_ERR(("CDrvWrap::WIA_drvUnInitializeWia, Error calling driver: drvUnInitializeWia failed with hr = 0x%08X", hr)); ReportMiniDriverError(lDevErrVal, NULL); } } __except(EXCEPTION_EXECUTE_HANDLER) { DBG_ERR(("CDrvWrap::WIA_drvUnInitializeWia, exception in drvUnInitializeWia: 0x%X", GetExceptionCode())); hr = WIA_ERROR_EXCEPTION_IN_DRIVER; } } else { DBG_WRN(("CDrvWrap::WIA_drvUnInitializeWia, attempting to call IWiaMiniDrv::drvUnInitializeWia when driver is not loaded")); } if (SUCCEEDED(hr)) { // TBD: Take a sync primitive? if(InterlockedDecrement(&m_lWiaTreeCount) == 0) { // No item trees left. // Note that we can't unload now, since the device still needs to // be unlocked, therefore simply mark it to be unloaded by // WIA_drvUnlockWiaDevice. if (m_bJITLoading) { m_bUnload = TRUE; } } } return hr; } // // End of wrapper methods for IWiaMiniDrv // /*****************************************************************************/ // // Private methods // /**************************************************************************\ * CDrvWrap::CreateDeviceControl * * Creates a IStiDeviceControl object to hand down to the driver during * its initialization. * * Arguments: * * None. * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT CDrvWrap::CreateDeviceControl() { HRESULT hr = E_FAIL; if (m_pDeviceInfo) { DWORD dwBusType = 0; DWORD dwControlTypeType = 0; // // Bus type is retrieved from dwHardwareConfiguration in the DeviceInformation struct // Use this to determine ControlTypeType // dwBusType = m_pDeviceInfo->dwHardwareConfiguration; // // Convert STI bit flags for device mode into HEL_ bit mask // if (dwBusType & (STI_HW_CONFIG_USB | STI_HW_CONFIG_SCSI)) { dwControlTypeType = HEL_DEVICE_TYPE_WDM; } else if (dwBusType & STI_HW_CONFIG_PARALLEL) { dwControlTypeType = HEL_DEVICE_TYPE_PARALLEL; } else if (dwBusType & STI_HW_CONFIG_SERIAL) { dwControlTypeType = HEL_DEVICE_TYPE_SERIAL; } else { DBG_WRN(("CDrvWrap::CreateDeviceControl, Cannot determine device control type, resorting to WDM")); dwControlTypeType = HEL_DEVICE_TYPE_WDM; } hr = NewDeviceControl(dwControlTypeType, (STI_DEVICE_CREATE_STATUS | STI_DEVICE_CREATE_FOR_MONITOR), m_pDeviceInfo->wszPortName, 0, &m_pIStiDeviceControl); if (FAILED(hr)) { m_pIStiDeviceControl = NULL; DBG_WRN(("CDrvWrap::CreateDeviceControl, failed to create new device control object")); } } else { DBG_WRN(("CDrvWrap::CreateDeviceControl, can't create IStiDeviceControl with NULL device information")); } return hr; } /**************************************************************************\ * CDrvWrap::InternalClear * * This will unload the driver, if it is loaded, and clear member * variables associated with the loaded driver state. * * Arguments: * * InternalClear * * Return Value: * * Status * * History: * * 11/06/2000 Original Version * \**************************************************************************/ HRESULT CDrvWrap::InternalClear() { HRESULT hr = S_OK; if (IsDriverLoaded()) { hr = UnLoadDriver(); if (FAILED(hr)) { DBG_ERR(("CDrvWrap::InternalClear, Error unloading driver")); } } m_hDriverDLL = NULL; m_pUsdIUnknown = NULL; m_pIStiUSD = NULL; m_pIWiaMiniDrv = NULL; m_pIStiDeviceControl = NULL; m_bJITLoading = FALSE; m_lWiaTreeCount = 0; m_bPreparedForUse = FALSE; m_bUnload = FALSE; return hr; } /**************************************************************************\ * CDrvWrap::::ReportMiniDriverError * * Report a mini driver error. The caller is responsible for * locking/unlocking the device. In most cases, the driver is already * locked when ReportMiniDriverError is called, so there is no need to lock * is again here. * * Arguments: * * lDevErr - Error value returned from the mini driver. * pszWhat - What the class driver was doing when the error ocured. * * Return Value: * * Status * * History: * * 10/20/1998 Original Version * \**************************************************************************/ HRESULT CDrvWrap::ReportMiniDriverError( LONG lDevErr, LPOLESTR pszWhat) { DBG_FN(CDrvWrap::ReportMiniDriverError); HRESULT hr = S_OK; LONG lFlags = 0; LONG lDevErrVal; if (lDevErr) { LPOLESTR pszErr = NULL; WIA_drvGetDeviceErrorStr(lFlags, lDevErr, &pszErr, &lDevErrVal); _try { if (FAILED(hr)) { pszErr = NULL; } if (pszWhat) { DBG_ERR(("Device error during %ws", pszWhat)); } if (pszErr) { DBG_ERR((" %ws", pszErr)); } } _finally { }; } else { hr = S_FALSE; } return hr; }