/***************************************************************************** * * (C) COPYRIGHT MICROSOFT CORPORATION, 2000 * * TITLE: WiaProc.cpp * * VERSION: 1.0 * * DATE: 2000/11/14 * * DESCRIPTION: Manages Wia side of things * *****************************************************************************/ #include #include #include "wiavideotest.h" static struct { DWORD dwWiaDevMgrCookie; DWORD dwSelectedDeviceCookie; IUnknown *pCreateCallback; IUnknown *pDeleteCallback; IUnknown *pDisconnectedCallback; IUnknown *pConnectedCallback; IGlobalInterfaceTable *pGIT; CRITICAL_SECTION CritSec; } LOCAL_GVAR = { NULL, NULL, NULL, NULL, NULL, NULL, 0, FALSE, NULL }; /****************************Local Function Prototypes********************/ HRESULT ClearDeviceList(); HRESULT AddItemToList(IWiaPropertyStorage *pItem, TCHAR *pszFriendlyName, TCHAR *pszDeviceID); WPARAM GetNumDevicesInList(); IWiaPropertyStorage* GetWiaStorage(WPARAM uiIndex); HRESULT CreateWiaDevMgr(IWiaDevMgr **ppDevMgr); HRESULT GetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, LONG *pnValue); HRESULT GetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, TCHAR *pszBuffer, UINT cbBuffer); HRESULT SetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, const PROPVARIANT *ppv, PROPID nNameFirst); HRESULT AppUtil_ConvertToWideString(const TCHAR *pszStringToConvert, WCHAR *pwszString, UINT cchString); HRESULT AppUtil_ConvertToTCHAR(const WCHAR *pwszStringToConvert, TCHAR *pszString, UINT cchString); HRESULT CreateRootItem(IWiaDevMgr *pDevMgr, const TCHAR *pszWiaDeviceID, IWiaItem **ppRootItem); HRESULT RegisterForEvents(IWiaDevMgr *pDevMgr); /////////////////////////////// // WiaProc_Init // HRESULT WiaProc_Init() { HRESULT hr = S_OK; IWiaDevMgr *pWiaDevMgr = NULL; if (LOCAL_GVAR.dwWiaDevMgrCookie != 0) { return S_OK; } __try { if (!InitializeCriticalSectionAndSpinCount(&LOCAL_GVAR.CritSec, MINLONG)) { hr = HRESULT_FROM_WIN32(::GetLastError()); } } __except(EXCEPTION_EXECUTE_HANDLER) { hr = E_OUTOFMEMORY; } if (hr == S_OK) { hr = CreateWiaDevMgr(&pWiaDevMgr); } if (hr == S_OK) { hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&LOCAL_GVAR.pGIT); } if (hr == S_OK) { LOCAL_GVAR.pGIT->RegisterInterfaceInGlobal(pWiaDevMgr, IID_IWiaDevMgr, &LOCAL_GVAR.dwWiaDevMgrCookie); } if (hr == S_OK) { hr = RegisterForEvents(pWiaDevMgr); } if (hr == S_OK) { WiaProc_PopulateDeviceList(); } if (pWiaDevMgr) { pWiaDevMgr->Release(); pWiaDevMgr = NULL; } return hr; } /////////////////////////////// // WiaProc_Term // HRESULT WiaProc_Term() { HRESULT hr = S_OK; ClearDeviceList(); if (LOCAL_GVAR.dwSelectedDeviceCookie != 0) { LOCAL_GVAR.pGIT->RevokeInterfaceFromGlobal(LOCAL_GVAR.dwSelectedDeviceCookie); LOCAL_GVAR.dwSelectedDeviceCookie = 0; } if (LOCAL_GVAR.dwWiaDevMgrCookie != 0) { LOCAL_GVAR.pGIT->RevokeInterfaceFromGlobal(LOCAL_GVAR.dwWiaDevMgrCookie); LOCAL_GVAR.dwWiaDevMgrCookie = 0; DeleteCriticalSection(&LOCAL_GVAR.CritSec); } if (LOCAL_GVAR.pCreateCallback) { LOCAL_GVAR.pCreateCallback->Release(); LOCAL_GVAR.pCreateCallback = NULL; } if (LOCAL_GVAR.pDeleteCallback) { LOCAL_GVAR.pDeleteCallback->Release(); LOCAL_GVAR.pDeleteCallback = NULL; } if (LOCAL_GVAR.pConnectedCallback) { LOCAL_GVAR.pConnectedCallback->Release(); LOCAL_GVAR.pConnectedCallback = NULL; } if (LOCAL_GVAR.pDisconnectedCallback) { LOCAL_GVAR.pDisconnectedCallback->Release(); LOCAL_GVAR.pDisconnectedCallback = NULL; } if (LOCAL_GVAR.pGIT) { LOCAL_GVAR.pGIT->Release(); LOCAL_GVAR.pGIT = NULL; } return hr; } /////////////////////////////// // WiaProc_CreateSelectedDevice // HRESULT WiaProc_CreateSelectedDevice(TCHAR *pszDeviceID, UINT cchDeviceID) { HRESULT hr = S_OK; WPARAM Index = 0; TCHAR szDeviceID[MAX_PATH] = {0}; IWiaDevMgr *pWiaDevMgr = NULL; if ((LOCAL_GVAR.dwWiaDevMgrCookie == 0) || (LOCAL_GVAR.pGIT == NULL)) { return E_POINTER; } hr = LOCAL_GVAR.pGIT->GetInterfaceFromGlobal(LOCAL_GVAR.dwWiaDevMgrCookie, IID_IWiaDevMgr, (void**)&pWiaDevMgr); if (pWiaDevMgr == NULL) { return E_POINTER; } LRESULT lResult = 0; lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_GETCURSEL, 0, 0); Index = (WPARAM) lResult; if (Index == LB_ERR) { hr = E_FAIL; } if (hr == S_OK) { IWiaItem *pSelectedDevice = NULL; LPARAM lParam = 0; lParam = SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_GETITEMDATA, Index, 0); IWiaPropertyStorage *pItem = (IWiaPropertyStorage*)lParam; if (pItem) { hr = GetProperty(pItem, WIA_DIP_DEV_ID, szDeviceID, sizeof(szDeviceID)/sizeof(TCHAR)); if (hr == S_OK) { hr = CreateRootItem(pWiaDevMgr, szDeviceID, &pSelectedDevice); } if (hr == S_OK) { hr = LOCAL_GVAR.pGIT->RegisterInterfaceInGlobal(pSelectedDevice, IID_IWiaItem, &LOCAL_GVAR.dwSelectedDeviceCookie); } if (pszDeviceID) { _tcsncpy(pszDeviceID, szDeviceID, cchDeviceID); } if (pSelectedDevice) { pSelectedDevice->Release(); pSelectedDevice = NULL; } } } if (pWiaDevMgr) { pWiaDevMgr->Release(); pWiaDevMgr = NULL; } return hr; } /////////////////////////////// // WiaProc_GetImageDirectory // HRESULT WiaProc_GetImageDirectory(TCHAR *pszImageDirectory, UINT cchImageDirectory) { HRESULT hr = S_OK; IWiaPropertyStorage *pStorage = NULL; IWiaItem *pSelectedDevice = NULL; if ((LOCAL_GVAR.dwSelectedDeviceCookie == 0) || (LOCAL_GVAR.pGIT == NULL) || (pszImageDirectory == NULL)) { return E_POINTER; } if (hr == S_OK) { hr = LOCAL_GVAR.pGIT->GetInterfaceFromGlobal(LOCAL_GVAR.dwSelectedDeviceCookie, IID_IWiaItem, (void**)&pSelectedDevice); } if (pSelectedDevice == NULL) { hr = E_POINTER; } if (hr == S_OK) { hr = pSelectedDevice->QueryInterface(IID_IWiaPropertyStorage, (void**) &pStorage); } if (hr == S_OK) { hr = GetProperty(pStorage, WIA_DPV_IMAGES_DIRECTORY, pszImageDirectory, cchImageDirectory); } if (pStorage) { pStorage->Release(); pStorage = NULL; } if (pSelectedDevice) { pSelectedDevice->Release(); pSelectedDevice = NULL; } return hr; } /////////////////////////////// // WiaProc_DeviceTakePicture // HRESULT WiaProc_DeviceTakePicture() { HRESULT hr = S_OK; IWiaItem *pSelectedDevice = NULL; if ((LOCAL_GVAR.dwSelectedDeviceCookie == 0) || (LOCAL_GVAR.pGIT == NULL)) { return E_POINTER; } if (hr == S_OK) { hr = LOCAL_GVAR.pGIT->GetInterfaceFromGlobal(LOCAL_GVAR.dwSelectedDeviceCookie, IID_IWiaItem, (void**)&pSelectedDevice); } if (pSelectedDevice == NULL) { hr = E_POINTER; } if (hr == S_OK) { IWiaItem *pUnused = NULL; hr = pSelectedDevice->DeviceCommand(0, &WIA_CMD_TAKE_PICTURE, &pUnused); if (pUnused) { pUnused->Release(); pUnused = NULL; } } if (pSelectedDevice) { pSelectedDevice->Release(); pSelectedDevice = NULL; } return hr; } /////////////////////////////// // ClearDeviceList // HRESULT ClearDeviceList() { HRESULT hr = S_OK; WPARAM NumDevices = 0; NumDevices = GetNumDevicesInList(); // // Free all the IWiaItem pointers we saved in our // list box. // if (NumDevices != LB_ERR) { for (WPARAM i = 0; i < NumDevices; i++) { IWiaPropertyStorage *pItem = NULL; pItem = GetWiaStorage(i); if (pItem) { pItem->Release(); } } } // // Empty the list // SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_RESETCONTENT, 0, 0); return hr; } /////////////////////////////// // WiaProc_PopulateDeviceList // HRESULT WiaProc_PopulateDeviceList() { HRESULT hr = S_OK; IEnumWIA_DEV_INFO *pEnum = NULL; IWiaDevMgr *pWiaDevMgr = NULL; hr = LOCAL_GVAR.pGIT->GetInterfaceFromGlobal(LOCAL_GVAR.dwWiaDevMgrCookie, IID_IWiaDevMgr, (void**)&pWiaDevMgr); if (pWiaDevMgr == NULL) { return E_POINTER; } // // Clear out the device list if it has any items in it. // ClearDeviceList(); if (hr == S_OK) { hr = pWiaDevMgr->EnumDeviceInfo(0, &pEnum); } while (hr == S_OK) { IWiaItem *pRootItem = NULL; IWiaPropertyStorage *pPropStorage = NULL; TCHAR szFriendlyName[MAX_PATH + 1] = {0}; TCHAR szWiaDeviceID[MAX_PATH + 1] = {0}; // // Get the next device in the enumeration. // hr = pEnum->Next(1, &pPropStorage, NULL); // // Get the device's Wia Device ID // if (hr == S_OK) { hr = GetProperty(pPropStorage, WIA_DIP_DEV_ID, szWiaDeviceID, sizeof(szWiaDeviceID)/sizeof(TCHAR)); } // // Get the device's Wia Device Name // if (hr == S_OK) { hr = GetProperty(pPropStorage, WIA_DIP_DEV_NAME, szFriendlyName, sizeof(szFriendlyName)/sizeof(TCHAR)); } // // We do not relesae the propstorage item because we store the pointer // in our list until we shutdown the app. // if (hr == S_OK) { AddItemToList(pPropStorage, szFriendlyName, szWiaDeviceID); } } SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_SETCURSEL, 0, 0); return hr; } /////////////////////////////// // RegisterForEvents // HRESULT RegisterForEvents(IWiaDevMgr *pWiaDevMgr) { HRESULT hr = S_OK; CWiaEvent *pWiaEvent = NULL; IWiaEventCallback *pIWiaEvent = NULL; if (pWiaDevMgr == NULL) { return E_POINTER; } // // Register our callback events // if (hr == S_OK) { // create the WiaEvent pWiaEvent = new CWiaEvent(); if (pWiaEvent == NULL) { hr = E_OUTOFMEMORY; } } if (hr == S_OK) { hr = pWiaEvent->QueryInterface(IID_IWiaEventCallback, (void**)&pIWiaEvent); } if (hr == S_OK) { hr = pWiaDevMgr->RegisterEventCallbackInterface(WIA_REGISTER_EVENT_CALLBACK, NULL, &WIA_EVENT_DEVICE_CONNECTED, pIWiaEvent, &LOCAL_GVAR.pConnectedCallback); hr = pWiaDevMgr->RegisterEventCallbackInterface(WIA_REGISTER_EVENT_CALLBACK, NULL, &WIA_EVENT_DEVICE_DISCONNECTED, pIWiaEvent, &LOCAL_GVAR.pDisconnectedCallback); hr = pWiaDevMgr->RegisterEventCallbackInterface(WIA_REGISTER_EVENT_CALLBACK, NULL, &WIA_EVENT_ITEM_CREATED, pIWiaEvent, &LOCAL_GVAR.pCreateCallback); hr = pWiaDevMgr->RegisterEventCallbackInterface(WIA_REGISTER_EVENT_CALLBACK, NULL, &WIA_EVENT_ITEM_DELETED, pIWiaEvent, &LOCAL_GVAR.pDeleteCallback); } // // We don't need to delete pWiaEvent since we are releasing it. // if (pIWiaEvent) { pIWiaEvent->Release(); pIWiaEvent = NULL; } return hr; } /////////////////////////////// // AddItemToList // HRESULT AddItemToList(IWiaPropertyStorage *pItem, TCHAR *pszFriendlyName, TCHAR *pszDeviceID) { HRESULT hr = S_OK; WPARAM Index = 0; if ((pItem == NULL) || (pszFriendlyName == NULL) || (pszDeviceID == NULL)) { hr = E_POINTER; return hr; } TCHAR szNewItem[MAX_PATH * 2] = {0}; _sntprintf(szNewItem, sizeof(szNewItem)/sizeof(TCHAR), TEXT("%s (%s)"), pszFriendlyName, pszDeviceID); LRESULT lResult = 0; lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_ADDSTRING, 0, (LPARAM) szNewItem); Index = (WPARAM) lResult; // // pItem already has an AddRef on it. // SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_SETITEMDATA, Index, (LPARAM) pItem); return hr; } /////////////////////////////// // GetNumDevicesInList // WPARAM GetNumDevicesInList() { LRESULT lResult = 0; WPARAM NumItems = 0; lResult = SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_GETCOUNT, 0, 0); NumItems = (WPARAM) lResult; return NumItems; } /////////////////////////////// // GetWiaStorage // IWiaPropertyStorage* GetWiaStorage(WPARAM Index) { LPARAM lParam = 0; IWiaPropertyStorage *pItem = NULL; lParam = SendDlgItemMessage(APP_GVAR.hwndMainDlg, IDC_LIST_WIA_DEVICES, LB_GETITEMDATA, Index, 0); pItem = (IWiaPropertyStorage*)lParam; return pItem; } /////////////////////////////// // CreateWiaDevMgr // HRESULT CreateWiaDevMgr(IWiaDevMgr **ppDevMgr) { HRESULT hr = S_OK; if (ppDevMgr == NULL) { hr = E_POINTER; return hr; } hr = CoCreateInstance(CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**) ppDevMgr); return hr; } /////////////////////////////// // WiaProc_GetProperty // // Generic // HRESULT WiaProc_GetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, PROPVARIANT *pPropVar) { HRESULT hr = S_OK; if ((pPropStorage == NULL) || (pPropVar == NULL)) { hr = E_POINTER; return hr; } PropVariantInit(pPropVar); PROPSPEC ps = {0}; ps.ulKind = PRSPEC_PROPID; ps.propid = nPropID; if (SUCCEEDED(hr)) { hr = pPropStorage->ReadMultiple(1, &ps, pPropVar); } return hr; } /////////////////////////////// // GetProperty // // For 'long' properties // HRESULT GetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, LONG *pnValue) { HRESULT hr = S_OK; if ((pPropStorage == NULL) || (pnValue == NULL)) { hr = E_POINTER; return hr; } PROPVARIANT pvPropValue; *pnValue = 0; PropVariantInit(&pvPropValue); hr = WiaProc_GetProperty(pPropStorage, nPropID, &pvPropValue); if (hr == S_OK) { if ((pvPropValue.vt == VT_I4) || (pvPropValue.vt == VT_UI4)) { *pnValue = pvPropValue.lVal; } } PropVariantClear(&pvPropValue); return hr; } /////////////////////////////// // GetProperty // // For 'string' properties // HRESULT GetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, TCHAR *pszBuffer, UINT cbBuffer) { HRESULT hr = S_OK; if ((pPropStorage == NULL) || (pszBuffer == NULL)) { hr = E_POINTER; return hr; } PROPVARIANT pvPropValue; PropVariantInit(&pvPropValue); hr = WiaProc_GetProperty(pPropStorage, nPropID, &pvPropValue); if (hr == S_OK) { if ((pvPropValue.vt == VT_LPWSTR) || (pvPropValue.vt == VT_BSTR)) { AppUtil_ConvertToTCHAR(pvPropValue.pwszVal, pszBuffer, cbBuffer); } } // // This frees the BSTR // PropVariantClear(&pvPropValue); return hr; } /////////////////////////////// // CreateRootItem // HRESULT CreateRootItem(IWiaDevMgr *pDevMgr, const TCHAR *pszWiaDeviceID, IWiaItem **ppRootItem) { HRESULT hr = S_OK; if ((pDevMgr == NULL) || (pszWiaDeviceID == NULL) || (ppRootItem == NULL)) { hr = E_POINTER; return hr; } if (hr == S_OK) { BOOL bRetry = TRUE; BSTR bstrDeviceID = NULL; WCHAR wszWiaDeviceID[MAX_PATH] = {0}; AppUtil_ConvertToWideString(pszWiaDeviceID, wszWiaDeviceID, sizeof(wszWiaDeviceID) / sizeof(WCHAR)); bstrDeviceID = SysAllocString(wszWiaDeviceID); for (UINT uiRetryCount = 0; (uiRetryCount < 5) && (bRetry); ++uiRetryCount) { hr = pDevMgr->CreateDevice(bstrDeviceID, ppRootItem); if (SUCCEEDED(hr)) { // // Break out of loop // bRetry = FALSE; } else if (hr == WIA_ERROR_BUSY) { // // Wait a little while before retrying // Sleep(200); } else { // // All other errors are considered fatal // bRetry = FALSE; } } if (bstrDeviceID) { SysFreeString(bstrDeviceID); bstrDeviceID = NULL; } } return hr; } /////////////////////////////// // SetProperty // // Generic // HRESULT SetProperty(IWiaPropertyStorage *pPropStorage, PROPID nPropID, const PROPVARIANT *ppv, PROPID nNameFirst) { HRESULT hr = 0; PROPSPEC ps = {0}; if ((pPropStorage == NULL) || (ppv == NULL)) { return E_POINTER; } ps.ulKind = PRSPEC_PROPID; ps.propid = nPropID; if (hr == S_OK) { hr = pPropStorage->WriteMultiple(1, &ps, ppv, nNameFirst); } return hr; } /////////////////////////////// // WiaProc_SetLastSavedImage // // For 'string' properties // HRESULT WiaProc_SetLastSavedImage(BSTR bstrLastSavedImage) { HRESULT hr = S_OK; IWiaItem *pSelectedDevice = NULL; IWiaPropertyStorage *pStorage = NULL; PROPVARIANT pv = {0}; if ((LOCAL_GVAR.dwSelectedDeviceCookie == 0) || (LOCAL_GVAR.pGIT == NULL)) { return E_POINTER; } EnterCriticalSection(&LOCAL_GVAR.CritSec); if (hr == S_OK) { hr = LOCAL_GVAR.pGIT->GetInterfaceFromGlobal(LOCAL_GVAR.dwSelectedDeviceCookie, IID_IWiaItem, (void**)&pSelectedDevice); } if (pSelectedDevice == NULL) { hr = E_POINTER; } if (hr == S_OK) { hr = pSelectedDevice->QueryInterface(IID_IWiaPropertyStorage, (void**)&pStorage); } if (hr == S_OK) { PropVariantInit(&pv); pv.vt = VT_BSTR; pv.bstrVal = bstrLastSavedImage; hr = SetProperty(pStorage, WIA_DPV_LAST_PICTURE_TAKEN, &pv, 2); } if (pStorage) { pStorage->Release(); pStorage = NULL; } if (pSelectedDevice) { pSelectedDevice->Release(); pSelectedDevice = NULL; } LeaveCriticalSection(&LOCAL_GVAR.CritSec); return hr; } /////////////////////////////// // WiaProc_PopulateItemList // HRESULT WiaProc_PopulateItemList() { HRESULT hr = S_OK; if (LOCAL_GVAR.dwSelectedDeviceCookie == 0) { return E_POINTER; } hr = ImageLst_PopulateWiaItemList(LOCAL_GVAR.pGIT, LOCAL_GVAR.dwSelectedDeviceCookie); return hr; } /////////////////////////////// // WiaProc_DestroySelectedDevice // HRESULT WiaProc_DestroySelectedDevice() { HRESULT hr = S_OK; if (LOCAL_GVAR.dwSelectedDeviceCookie == 0) { return E_POINTER; } ImageLst_CancelLoadAndWait(5000); if ((LOCAL_GVAR.dwSelectedDeviceCookie != 0) && (LOCAL_GVAR.pGIT != NULL)) { LOCAL_GVAR.pGIT->RevokeInterfaceFromGlobal(LOCAL_GVAR.dwSelectedDeviceCookie); LOCAL_GVAR.dwSelectedDeviceCookie = 0; } ImageLst_Clear(); return hr; }