HRESULT EnumerateWiaDevices( IWiaDevMgr *pWiaDevMgr )
{
    //
    // Validate arguments
    //
    if (NULL == pWiaDevMgr)
    {
        return E_INVALIDARG;
    }

    //
    // Get a device enumerator interface
    //
    IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;
    HRESULT hr = pWiaDevMgr->EnumDeviceInfo( WIA_DEVINFO_ENUM_LOCAL, &pWiaEnumDevInfo );
    if (SUCCEEDED(hr))
    {
        //
        // Reset the device enumerator to the beginning of the list
        //
        hr = pWiaEnumDevInfo->Reset();
        if (SUCCEEDED(hr))
        {
            //
            // We will loop until we get an error or pWiaEnumDevInfo->Next returns
            // S_FALSE to signal the end of the list.
            //
            while (S_OK == hr)
            {
                //
                // Get the next device's property storage interface pointer
                //
                IWiaPropertyStorage *pWiaPropertyStorage = NULL;
                hr = pWiaEnumDevInfo->Next( 1, &pWiaPropertyStorage, NULL );

                //
                // pWiaEnumDevInfo->Next will return S_FALSE when the list is
                // exhausted, so check for S_OK before using the returned
                // value.
                //
                if (hr == S_OK)
                {
                    //
                    // Do something with the device's IWiaPropertyStorage*
                    //
                    ReadSomeWiaProperties( pWiaPropertyStorage );

                    //
                    // Call a helper function to create the device
                    // and do some stuff with it.
                    //
                    CreateWiaDeviceAndDoSomeStuff( pWiaDevMgr, pWiaPropertyStorage );

                    //
                    // Release the device's IWiaPropertyStorage*
                    //
                    pWiaPropertyStorage->Release();
                    pWiaPropertyStorage = NULL;
                }
                else if (FAILED(hr))
                {
                    //
                    // Report that an error occurred during enumeration
                    //
                    ReportError( TEXT("Error calling pWiaEnumDevInfo->Next"), hr );
                }
            }
            
            //
            // If the result of the enumeration is S_FALSE, since this
            // is normal, we will change it to S_OK.
            //
            if (S_FALSE == hr)
            {
                hr = S_OK;
            }
        }
        else
        {
            //
            // Report that an error occurred calling Reset()
            //
            ReportError( TEXT("Error calling IEnumWIA_DEV_INFO::Reset()"), hr );
        }

        //
        // Release the enumerator
        //
        pWiaEnumDevInfo->Release();
        pWiaEnumDevInfo = NULL;
    }
    else
    {
        //
        // Report that an error occurred trying to create the enumerator
        //
        ReportError( TEXT("Error calling IWiaDevMgr::EnumDeviceInfo"), hr );
    }

    //
    // Return the result of the enumeration
    //
    return hr;
}
//This function enumerates WIA devices and then creates an instance of each device.
//After that it calls EnumerateAndDownloadItems() on the root item got from creation of device.
HRESULT EnumerateWiaDevices( IWiaDevMgr2 *pWiaDevMgr2 )
{
    // Validate arguments
    if (NULL == pWiaDevMgr2)
    {
        HRESULT hr = E_INVALIDARG;
        ReportError(TEXT("Invalid argument passed to EnumerateWiaDevices()"),hr);
        return hr;
    }

    // Get a device enumerator interface
    IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;
    HRESULT hr = pWiaDevMgr2->EnumDeviceInfo( WIA_DEVINFO_ENUM_LOCAL, &pWiaEnumDevInfo );
    if (SUCCEEDED(hr))
    {
        // Reset the device enumerator to the beginning of the list
        hr = pWiaEnumDevInfo->Reset();
        if (SUCCEEDED(hr))
        {
            // We will loop until we get an error or pWiaEnumDevInfo->Next returns
            // S_FALSE to signal the end of the list.
            while (S_OK == hr)
            {
                // Get the next device's property storage interface pointer
                IWiaPropertyStorage *pWiaPropertyStorage = NULL;
                hr = pWiaEnumDevInfo->Next( 1, &pWiaPropertyStorage, NULL );

                // pWiaEnumDevInfo->Next will return S_FALSE when the list is
                // exhausted, so check for S_OK before using the returned
                // value.
                if (hr == S_OK)
                {
                    // Read some device properties - Device ID,name and descripion and return Device ID needed for creating Device
                    BSTR bstrDeviceID = NULL;
                    HRESULT hr1 = ReadWiaPropsAndGetDeviceID( pWiaPropertyStorage ,&bstrDeviceID);
                    if(SUCCEEDED(hr1))
                    {
                        // Call a function to create the device using device ID 
                        IWiaItem2 *pWiaRootItem2 = NULL;
                        hr1 = pWiaDevMgr2->CreateDevice( 0, bstrDeviceID, &pWiaRootItem2 );
                        if(SUCCEEDED(hr1))
                        {
                            // Enumerate items and for each item do transfer
                            hr1 = EnumerateAndDownloadItems( pWiaRootItem2 );
                            if(FAILED(hr1))
                            {
                                ReportError(TEXT("EnumerateAndDownloadItems() failed in EnumerateWiaDevices()"),hr1);
                            }
                            //Release pWiaRootItem2
                            pWiaRootItem2->Release();
                            pWiaRootItem2 = NULL;
                        }
                        else
                        {
                            ReportError(TEXT("Error calling IWiaDevMgr2::CreateDevice()"),hr1);
                        }
                    }
                    else
                    {
                        ReportError(TEXT("ReadWiaPropsAndGetDeviceID() failed in EnumerateWiaDevices()"),hr1);
                    }
                        
                    // Release the device's IWiaPropertyStorage*
                    pWiaPropertyStorage->Release();
                    pWiaPropertyStorage = NULL;
                }
                else if (FAILED(hr))
                {
                    // Report that an error occurred during enumeration
                    ReportError( TEXT("Error calling IEnumWIA_DEV_INFO::Next()"), hr );
                }
            }
            
            //
            // If the result of the enumeration is S_FALSE, since this
            // is normal, we will change it to S_OK.
            //
            if (S_FALSE == hr)
            {
                hr = S_OK;
            }
        }
        else
        {
            // Report that an error occurred calling Reset()
            ReportError( TEXT("Error calling IEnumWIA_DEV_INFO::Reset()"), hr );
        }
        // Release the enumerator
        pWiaEnumDevInfo->Release();
        pWiaEnumDevInfo = NULL;
    }
    else
    {
        // Report that an error occurred trying to create the enumerator
        ReportError( TEXT("Error calling IWiaDevMgr2::EnumDeviceInfo"), hr );
    }

    // Return the result of the enumeration
    return hr;
}
HRESULT WIACamera::Initialize()
{
	// CoInitialize(NULL);
	CoInitializeEx(NULL, COINIT_MULTITHREADED);

    IEnumWIA_DEV_INFO   *pWiaEnumDevInfo    = NULL;
	
	//
    // Create an instance of the device manager
    //
	HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&m_pWiaDevMgr );
    hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER, IID_IWiaVideo, (void**) &m_pWiaVideo);

	if (SUCCEEDED(hr)) {
		//
		// Enumerate WIA devices on the system
		//
		hr = m_pWiaDevMgr->EnumDeviceInfo(WIA_DEVINFO_ENUM_LOCAL, &pWiaEnumDevInfo);
	}

	//
	// Reset the enumeration to start at the beginning of the list.
	//
	if (SUCCEEDED(hr)) {
		//
		// Call Reset on Enumerator
		//
		hr = pWiaEnumDevInfo->Reset();
	}

    BOOL bFound = FALSE;
	while ( SUCCEEDED(hr) ) {
		IWiaPropertyStorage *pIWiaPropStg	= NULL;
	    ULONG               ulFetched		= NULL;
		//
		// Get the next WIA device
		//
		hr = pWiaEnumDevInfo->Next(1, &pIWiaPropStg, &ulFetched);

		if (hr == S_OK)	{
			//
			// Get the device type of the device
			//
			PROPSPEC    PropSpec[3];
			PROPVARIANT PropVar[3];
			memset(PropVar,0,sizeof(PropVar));
			PropSpec[0].ulKind = PRSPEC_PROPID;
			PropSpec[0].propid = WIA_DIP_DEV_ID;
			PropSpec[1].ulKind = PRSPEC_PROPID;
			PropSpec[1].propid = WIA_DIP_DEV_TYPE;
			PropSpec[2].ulKind = PRSPEC_PROPID;
			PropSpec[2].propid = WIA_DIP_DEV_NAME;

			//
			// Get the type and the ID of each device
			//
			hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC),
											PropSpec, PropVar);

			//
			// If the device is a streaming video device/digital camera,
			//  get its ID
			//
			if (GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeStreamingVideo 
				|| GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeDigitalCamera) {
				std::wcerr	<< "WIA_DIP_DEV_ID :\t"		<< PropVar[0].bstrVal << std::endl
							<< "WIA_DIP_DEV_NAME :\t"	<< PropVar[2].bstrVal << std::endl;	
				bFound = TRUE;

				const size_t BUFFER_SIZE = 1024;
				char buf[BUFFER_SIZE];
				_bstr_t bstrIntermediate;

				bstrIntermediate.Assign(PropVar[0].bstrVal);
				sprintf_s((char*)buf, BUFFER_SIZE, "%s", (LPCTSTR)bstrIntermediate);
				char* strID = new char [strlen(buf)+1];
				strcpy_s( strID, strlen(buf)+1, buf );
				m_vCameraID.push_back(strID);

				bstrIntermediate.Assign(PropVar[2].bstrVal);
				sprintf_s((char*)buf, BUFFER_SIZE, "%s", (LPCTSTR)bstrIntermediate);
				char* strName = new char [strlen(buf)+1];
				strcpy_s( strID, strlen(buf)+1, buf );
				m_vCameraName.push_back(strName);
				delete [] strID;
				delete [] strName;

				//
				// Create a WIA device and get the recommended
				// images directory
				//
				IWiaItem *pRootItem = NULL;
				hr = m_pWiaDevMgr->CreateDevice(PropVar[0].bstrVal,
											&pRootItem);
				if (GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeStreamingVideo) {
					// ビデオカメラ特有の処理
					m_pCaptureFunc.push_back( &WIACamera::VideoCameraCapture );
				} else {
					// デジタルカメラ特有の処理
					m_pCaptureFunc.push_back( &WIACamera::DigitalCameraCapture );
				}
				if (SUCCEEDED(hr)) { 
					m_vRootItem.push_back(pRootItem);
				} else {
					m_vRootItem.push_back(NULL);
					throw "Error:\n";
					return hr;
				}
			}
		} else {
			break;
		}

		if (pIWiaPropStg) {
			pIWiaPropStg->Release();
			pIWiaPropStg = NULL;
		}
	}

	if (pWiaEnumDevInfo) {
		pWiaEnumDevInfo->Release();
		pWiaEnumDevInfo = NULL;
	}
	if (!bFound)
	{
		//
		// We did not find any WIA video streaming devices.  There is nothing left
		// to do.  Set result to E_FAIL
		//
		hr = E_FAIL;
		return hr;
	}


	m_iCount = (unsigned int)m_vRootItem.size();
	
    //
    // Return the result of creating the device manager
    //
    return hr;
}