/****************************************************************************** * * (C) COPYRIGHT MICROSOFT CORP., 2000 * * TITLE: Device.cpp * * VERSION: 1.0 * * AUTHOR: KeisukeT * * DATE: 27 Mar, 2000 * * DESCRIPTION: * Device class for WIA class installer. * * *******************************************************************************/ // // Precompiled header // #include "precomp.h" #pragma hdrstop #define INITGUID #include "device.h" #include "sti.h" #include "stiregi.h" #include #include #include #include #include // // Parsinc character used to separate field type from value in registry data section // #define FIELD_DELIMETER TEXT(',') BOOL CDevice::CollectNames( VOID ) { BOOL bRet; HANDLE hDevInfo; GUID Guid; DWORD dwRequired; DWORD Idx; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; TCHAR szTempBuffer[MAX_DESCRIPTION]; HKEY hKeyInterface; HKEY hKeyDevice; DebugTrace(TRACE_PROC_ENTER,(("CDevice::CollectNames: Enter...\r\n"))); // // Initialize local. // bRet = FALSE; hDevInfo = INVALID_HANDLE_VALUE; Guid = GUID_DEVCLASS_IMAGE; dwRequired = 0; Idx = 0; hKeyInterface = (HKEY)INVALID_HANDLE_VALUE; hKeyDevice = (HKEY)INVALID_HANDLE_VALUE; memset(szTempBuffer, 0, sizeof(szTempBuffer)); memset(&spDevInfoData, 0, sizeof(spDevInfoData)); memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData)); // // Reset device name/ID array. // m_csaAllNames.Cleanup(); m_csaAllId.Cleanup(); // // Get all of installed WIA "devnode" device info set. // hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE); if (hDevInfo == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! SetupDiGetClassDevs (devnodes) fails. Err=0x%x\n"), GetLastError())); bRet = FALSE; goto CollectNames_return; } // // Enum WIA devnode device friendly name and add them to array. // DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Looking for DevNodes.\r\n"))); spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA); for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) { // // Open device registry key. // hKeyDevice = SetupDiOpenDevRegKey(hDevInfo, &spDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); if (INVALID_HANDLE_VALUE != hKeyDevice) { // // Get FriendlyName. // dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0'))); if (RegQueryValueEx(hKeyDevice, REGSTR_VAL_FRIENDLY_NAME, NULL, NULL, (LPBYTE)szTempBuffer, &dwRequired) == ERROR_SUCCESS) { // // FriendlyName is found in this device regisgry. Add to the list if valid. // if(0 != lstrlen(szTempBuffer)) { DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device name.\r\n"), szTempBuffer)); m_csaAllNames.Add((LPCTSTR)szTempBuffer); } else { // if(0 != lstrlen(szTempBuffer)) DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid FriendleName (length=0).\r\n"))); } // if(0 != lstrlen(szTempBuffer)) } else { // if (RegQueryValueEx() DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get FriendlyName. Err=0x%x\r\n"), GetLastError())); } // if (RegQueryValueEx() // // Get DeviceID. // dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0'))); if (RegQueryValueEx(hKeyDevice, REGSTR_VAL_DEVICE_ID, NULL, NULL, (LPBYTE)szTempBuffer, &dwRequired) == ERROR_SUCCESS) { // // DeviceID is found in this device regisgry. Add to the list if valid. // if(0 != lstrlen(szTempBuffer)) { DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device ID.\r\n"), szTempBuffer)); m_csaAllId.Add((LPCTSTR)szTempBuffer); } else { // if(0 != lstrlen(szTempBuffer)) DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid DeviceID (length=0).\r\n"))); } // if(0 != lstrlen(szTempBuffer)) } else { // if (RegQueryValueEx() DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get DeviceID. Err=0x%x\r\n"), GetLastError())); } // if (RegQueryValueEx() // // Close regkey and continue. // RegCloseKey(hKeyDevice); hKeyInterface = (HKEY)INVALID_HANDLE_VALUE; szTempBuffer[0] = TEXT('\0'); } else { // if (hKeyDevice != INVALID_HANDLE_VALUE) DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Unable to open Device(%d) RegKey. Err=0x%x\r\n"), Idx, GetLastError())); } // if (hKeyDevice != INVALID_HANDLE_VALUE) } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) // // Free "devnode" device info set. // SetupDiDestroyDeviceInfoList(hDevInfo); hDevInfo = INVALID_HANDLE_VALUE; // // Enum WIA interface-only device friendly name and add them to array. // DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Looking for Interfaces.\r\n"))); hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PROFILE); if (hDevInfo == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! SetupDiGetClassDevs (inferfase) fails. Err=0x%x\n"), GetLastError())); bRet = FALSE; goto CollectNames_return; } spDevInterfaceData.cbSize = sizeof (spDevInterfaceData); for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) { hKeyInterface = SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &spDevInterfaceData, 0, KEY_READ); if (hKeyInterface != INVALID_HANDLE_VALUE) { // // Get FriendlyName. // dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0'))); if (RegQueryValueEx(hKeyInterface, REGSTR_VAL_FRIENDLY_NAME, NULL, NULL, (LPBYTE)szTempBuffer, &dwRequired) == ERROR_SUCCESS) { // // FriendlyName is found in this interface. Add to the list if valid. // if(0 != lstrlen(szTempBuffer)) { DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device name (interface).\r\n"), szTempBuffer)); m_csaAllNames.Add((LPCTSTR)szTempBuffer); } else { // if(0 != lstrlen(szTempBuffer)) DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid FriendleName (length=0).\r\n"))); } // if(0 != lstrlen(szTempBuffer)) } else { // if (RegQueryValueEx() DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get FriendlyName. Err=0x%x\r\n"), GetLastError())); } // if (RegQueryValueEx() // // Get DeviceID. // dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0'))); if (RegQueryValueEx(hKeyInterface, REGSTR_VAL_DEVICE_ID, NULL, NULL, (LPBYTE)szTempBuffer, &dwRequired) == ERROR_SUCCESS) { // // DeviceID is found in this interface. Add to the list if valid. // if(0 != lstrlen(szTempBuffer)) { DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device ID (interface).\r\n"), szTempBuffer)); m_csaAllId.Add((LPCTSTR)szTempBuffer); } else { // if(0 != lstrlen(szTempBuffer)) DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid DeviceID (length=0).\r\n"))); } // if(0 != lstrlen(szTempBuffer)) } else { // if (RegQueryValueEx() DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get DeviceID. Err=0x%x\r\n"), GetLastError())); } // if (RegQueryValueEx() // // Close registry key and continue. // RegCloseKey(hKeyInterface); hKeyInterface = (HKEY)INVALID_HANDLE_VALUE; szTempBuffer[0] = TEXT('\0'); } else { // if (hKeyInterface != INVALID_HANDLE_VALUE) DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Unable to open Interface(%d) RegKey. Err=0x%x\r\n"), Idx, GetLastError())); } // if (hKeyInterface != INVALID_HANDLE_VALUE) } // for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) // // Operation succeeded. // bRet = TRUE; CollectNames_return: // // Clean up. // if(INVALID_HANDLE_VALUE != hDevInfo){ SetupDiDestroyDeviceInfoList(hDevInfo); } if(INVALID_HANDLE_VALUE != hKeyInterface){ RegCloseKey(hKeyInterface); } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::CollectNames: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::CollectNames() // For a device w/ devnode. CDevice::CDevice( HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoData, BOOL bIsPnP ) { HKEY hkDevice; // // Initizlize local. // hkDevice = (HKEY)INVALID_HANDLE_VALUE; // // Initialize member. // m_hMutex = (HANDLE)NULL; m_hDevInfo = hDevInfo; m_pspDevInfoData = pspDevInfoData; m_bIsPnP = bIsPnP; m_bDefaultDevice = FALSE; m_bVideoDevice = FALSE; m_bInfProceeded = FALSE; m_bInterfaceOnly = FALSE; m_bIsMigration = FALSE; m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE; m_dwCapabilities = 0; m_dwInterfaceIndex = INVALID_DEVICE_INDEX; m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL; m_pExtraDeviceData = NULL; m_csFriendlyName.Empty(); m_csInf.Empty(); m_csInstallSection.Empty(); m_csDriverDescription.Empty(); m_csPort.Empty(); m_csDeviceID.Empty(); // // In case of upgrade, use original FriendlyName. // hkDevice = SetupDiOpenDevRegKey(m_hDevInfo, m_pspDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); if(INVALID_HANDLE_VALUE != hkDevice){ // // Device registry found. Read its FriendlyName. // m_csDriverDescription.Load(hkDevice, FRIENDLYNAME); m_csDeviceID.Load(hkDevice, REGSTR_VAL_DEVICE_ID); m_csFriendlyName.Load(hkDevice, FRIENDLYNAME); RegCloseKey(hkDevice); hkDevice = (HKEY)INVALID_HANDLE_VALUE; } // if(INVALID_HANDLE_VALUE != hkDevice) // // Get the number of installed devices. // GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice); } // CDevice::CDevice() // For a interface-only device. CDevice::CDevice( HDEVINFO hDevInfo, DWORD dwDeviceIndex ) { // // Initialize member. // m_hMutex = (HANDLE)NULL; m_hDevInfo = hDevInfo; m_pspDevInfoData = NULL; m_bIsPnP = FALSE; m_bDefaultDevice = FALSE; m_bVideoDevice = FALSE; m_bInfProceeded = FALSE; m_bInterfaceOnly = TRUE; m_bIsMigration = FALSE; m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE; m_dwCapabilities = 0; m_dwInterfaceIndex = dwDeviceIndex; m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL; m_pExtraDeviceData = NULL; m_csFriendlyName.Empty(); m_csInf.Empty(); m_csInstallSection.Empty(); m_csDriverDescription.Empty(); m_csPort.Empty(); m_csDeviceID.Empty(); // // Get the number of installed devices. // GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice); } // CDevice::CDevice() // For a interface-only device. CDevice::CDevice( PDEVICE_INFO pMigratingDevice ) { TCHAR StringBuffer[MAX_PATH+1]; TCHAR WindowsDir[MAX_PATH+1]; // // Initialize local. // memset(StringBuffer, 0, sizeof(StringBuffer)); memset(WindowsDir, 0, sizeof(WindowsDir)); // // Initialize member. // m_hMutex = (HANDLE)NULL; m_hDevInfo = NULL; m_pspDevInfoData = NULL; m_bIsPnP = FALSE; m_bDefaultDevice = FALSE; m_bVideoDevice = FALSE; m_bInfProceeded = FALSE; m_bInterfaceOnly = TRUE; m_bIsMigration = TRUE; m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE; m_dwCapabilities = 0; m_dwInterfaceIndex = INVALID_DEVICE_INDEX; m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL; // // Copy migration data. // AtoT(StringBuffer, pMigratingDevice->pszInfPath); m_csInf = StringBuffer; if(0 != GetWindowsDirectory(WindowsDir, MAX_PATH)){ _sntprintf(StringBuffer, ARRAYSIZE(StringBuffer)-1, TEXT("%ws\\inf\\%ws"), WindowsDir, (LPTSTR)m_csInf); m_csInf = StringBuffer; } // if(0 != GetWindowsDirectory(WindowsDir, MAX_PATH)) AtoT(StringBuffer, pMigratingDevice->pszInfSection); m_csInstallSection = StringBuffer; AtoT(StringBuffer, pMigratingDevice->pszFriendlyName); m_csDriverDescription = StringBuffer; AtoT(StringBuffer, pMigratingDevice->pszFriendlyName); m_csFriendlyName = StringBuffer; AtoT(StringBuffer, pMigratingDevice->pszCreateFileName); m_csPort = StringBuffer; m_pExtraDeviceData = pMigratingDevice->pDeviceDataParam; m_csDeviceID.Empty(); // // Get the number of installed devices. // GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice); } // CDevice::CDevice() CDevice::~CDevice( ) { HKEY hkNameStore; if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){ // // Delete FriendlyName and DeviceId in name store. // RegDeleteKey(hkNameStore, m_csFriendlyName); RegDeleteKey(hkNameStore, m_csDeviceID); RegCloseKey(hkNameStore); } // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)) // // Make sure Mutex is released. // ReleaseInstallerMutex(); } // CDevice::~CDevice() BOOL CDevice::IsSameDevice( HDEVINFO hDevInfo, PSP_DEVINFO_DATA pspDevInfoSet ) { BOOL bRet; SP_DRVINFO_DATA spDrvInfoData; DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsSameDevice: Enter...\r\n"))); // // Initialize local. // bRet = FALSE; memset(&spDrvInfoData, 0, sizeof(spDrvInfoData)); // // Get default FriendlyName. It's used to check if it's same device or not. // spDrvInfoData.cbSize = sizeof (SP_DRVINFO_DATA); if (!SetupDiGetSelectedDriver (hDevInfo, pspDevInfoSet, &spDrvInfoData)){ bRet = FALSE; goto IsSameDevice_return; } // if (SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDevInfoData)) // // See if it has same description of current device. (TRUE=same) // bRet = (0 == lstrcmp((LPCTSTR)spDrvInfoData.Description, (LPCTSTR)m_csPdoDescription)); IsSameDevice_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsSameDevice: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::IsSameDevice() BOOL CDevice::IsFriendlyNameUnique( LPTSTR szFriendlyName ) // // Note: // Before calling this function, caller has to make sure mutex is acquired. // { BOOL bRet; DWORD Idx; DWORD dwNumberOfName; DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsFriendlyNameUnique: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; Idx = 0; dwNumberOfName = m_csaAllNames.Count(); // // If given name is same as generated one, it's unique. // if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName))){ bRet = TRUE; goto IsFriendlyNameUnique_return; } // if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName))) // // Check any existing name matches given name. // for (Idx = 0; Idx < dwNumberOfName; Idx++) { DebugTrace(TRACE_STATUS,(("CDevice::IsFriendlyNameUnique: Name compare %ws and %ws.\r\n"),m_csaAllNames[Idx], szFriendlyName)); if (0 == lstrcmpi(m_csaAllNames[Idx], szFriendlyName)){ bRet = FALSE; goto IsFriendlyNameUnique_return; } } // for (Idx = 0; Idx < dwNumberOfName; Idx) // // Look in name store. // if(IsNameAlreadyStored(szFriendlyName)){ bRet = FALSE; goto IsFriendlyNameUnique_return; } // if(IsNameAlreadyStored(szFriendlyName)) // // This device name is unique. // bRet = TRUE; IsFriendlyNameUnique_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsFriendlyNameUnique: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::IsFriendlyNameUnique() BOOL CDevice::IsDeviceIdUnique( LPTSTR szDeviceId ) { BOOL bRet; DWORD Idx; DWORD dwNumberOfId; DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsDeviceIdUnique: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; Idx = 0; dwNumberOfId = m_csaAllId.Count(); // // If given ID is same as generated one, it's unique. // if(0 == lstrcmp(szDeviceId, (LPTSTR)(m_csDeviceID))){ bRet = TRUE; goto IsDeviceIdUnique_return; } // if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName))) // // Check any existing name matches given name. // for (Idx = 0; Idx < dwNumberOfId; Idx++) { DebugTrace(TRACE_STATUS,(("CDevice::IsDeviceIdUnique: DeviceId compare %ws and %ws.\r\n"),m_csaAllId[Idx], szDeviceId)); if (0 == lstrcmpi(m_csaAllId[Idx], szDeviceId)){ bRet = FALSE; goto IsDeviceIdUnique_return; } // if (0 == lstrcmpi(m_csaAllId[Idx], szFriendlyName)) } // for (Idx = 0; Idx < dwNumberOfName; Idx) // // Look in name store. // if(IsNameAlreadyStored(szDeviceId)){ bRet = FALSE; goto IsDeviceIdUnique_return; } // if(IsNameAlreadyStored(szFriendlyName)) // // This device name is unique. // bRet = TRUE; IsDeviceIdUnique_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsDeviceIdUnique: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::IsDeviceIdUnique() BOOL CDevice::NameDefaultUniqueName( VOID ) { SP_DRVINFO_DATA spDrvInfoData; TCHAR szFriendly[MAX_DESCRIPTION]; TCHAR szDescription[MAX_DESCRIPTION]; UINT i; BOOL bRet; HKEY hkNameStore; DWORD dwError; DebugTrace(TRACE_PROC_ENTER,(("CDevice::NameDefaultUniqueName: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; hkNameStore = (HKEY)INVALID_HANDLE_VALUE; memset(szFriendly, 0, sizeof(szFriendly)); memset(szDescription, 0, sizeof(szDescription)); memset(&spDrvInfoData, 0, sizeof(spDrvInfoData)); // // Acquire mutex to make sure not duplicating FriendlyName/DeviceId. // dwError = AcquireInstallerMutex(MAX_MUTEXTIMEOUT); if(ERROR_SUCCESS != dwError){ // it must be done at least in 60 sec. if(WAIT_ABANDONED == dwError){ DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Mutex abandoned. Continue...\r\n")); } else if(WAIT_TIMEOUT == dwError){ DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to acquire mutex in 60 sec. Bail out.\r\n")); bRet = FALSE; goto NameDefaultUniqueName_return; } // else if(WAIT_TIMEOUT == dwError) } // if(ERROR_SUCCESS != AcquireInstallerMutex(60000)) // // Get all installed WIA device friendly name. // CollectNames(); // // Generate unique device ID. // if(m_csDeviceID.IsEmpty()){ GenerateUniqueDeviceId(); } // if(m_csDeviceID.IsEmpty()) if(m_csFriendlyName.IsEmpty()){ // // Get default FriendlyName. It's used to check if it's same device or not. // spDrvInfoData.cbSize = sizeof (SP_DRVINFO_DATA); if (!SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDrvInfoData)){ bRet = FALSE; goto NameDefaultUniqueName_return; } // if (SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDevInfoData)) // // Copy default Device description. (= default FriendlyName) // Also set Vnedor name. // m_csVendor = (LPCTSTR)spDrvInfoData.MfgName; m_csPdoDescription = (LPCTSTR)spDrvInfoData.Description; // // Find unique name for this device. // if(m_csDriverDescription.IsEmpty()){ lstrcpyn(szDescription, m_csPdoDescription, ARRAYSIZE(szDescription)-1); m_csDriverDescription = szDescription; } else { lstrcpyn(szDescription, m_csDriverDescription, ARRAYSIZE(szDescription)-1); } lstrcpyn(szFriendly, szDescription, ARRAYSIZE(szFriendly)-1); for (i = 2; !IsFriendlyNameUnique(szFriendly); i++) { _sntprintf(szFriendly, ARRAYSIZE(szFriendly)-1, TEXT("%ws #%d"), szDescription, i); } // // Set created FriendlyName. // m_csFriendlyName = szFriendly; } // if(m_csFriendlyName.IsEmpty()) // // Save FriendlyName and DeviceId in registry. It'll be deleted when installation is completed. // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){ HKEY hkTemp; hkTemp = (HKEY)INVALID_HANDLE_VALUE; // // Create FriendlyName key. // if(ERROR_SUCCESS == RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp)){ RegCloseKey(hkTemp); hkTemp = (HKEY)INVALID_HANDLE_VALUE; } else { DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create %s key.\r\n", (LPTSTR)m_csFriendlyName)); } // if(ERROR_SUCCESS != RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp)) // // Create DeviceId key. // if(ERROR_SUCCESS == RegCreateKey(hkNameStore, (LPTSTR)m_csDeviceID, &hkTemp)){ RegCloseKey(hkTemp); hkTemp = (HKEY)INVALID_HANDLE_VALUE; } else { DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create %s key.\r\n", (LPTSTR)m_csDeviceID)); } // if(ERROR_SUCCESS != RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp)) RegCloseKey(hkNameStore); } else { // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)) DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create NameStore key.\r\n")); } // else(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)) // // Operation succeeded. // DebugTrace(TRACE_STATUS,(("CDevice::NameDefaultUniqueName: Device default name=%ws.\r\n"), (LPTSTR)m_csFriendlyName)); bRet = TRUE; NameDefaultUniqueName_return: // // Release mutex. ReleaseInstallerMutex() will handle invalid handle also, so we can call anyway. // ReleaseInstallerMutex(); DebugTrace(TRACE_PROC_LEAVE,(("CDevice::NameDefaultUniqueName: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::NameDefaultUniqueName() BOOL CDevice::GenerateUniqueDeviceId( VOID ) { DWORD Idx; BOOL bRet; TCHAR szDeviceId[MAX_DESCRIPTION]; DebugTrace(TRACE_PROC_ENTER,(("CDevice::GenerateUniqueDeviceId: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; memset(szDeviceId, 0, sizeof(szDeviceId)); // // Find unique name for this device. // _sntprintf(szDeviceId, ARRAYSIZE(szDeviceId)-1, TEXT("%ws\\%04d"), WIA_GUIDSTRING, 0); for (Idx = 1; !IsDeviceIdUnique(szDeviceId); Idx++) { _sntprintf(szDeviceId, ARRAYSIZE(szDeviceId)-1, TEXT("%ws\\%04d"), WIA_GUIDSTRING, Idx); } // // Set created hardwareId. // m_csDeviceID = szDeviceId; // // Operation succeeded. // DebugTrace(TRACE_STATUS,(("CDevice::GenerateUniqueDeviceId: DeviceID=%ws.\r\n"), (LPTSTR)m_csDeviceID)); bRet = TRUE; // GenerateUniqueDeviceId_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::GenerateUniqueDeviceId: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::GenerateUniqueDeviceId() BOOL CDevice::Install( ) /*++ Routine Description: Worker function for DIF_INSTALL setup message Arguments: none Return Value: TRUE - successful FALSE - non successful --*/ { BOOL bRet; DebugTrace(TRACE_PROC_ENTER,(("CDevice::Install: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; // // Class installer only handles file copy. // if(IsMigration()){ CreateDeviceInterfaceAndInstall(); } else { // if(IsMigration()) if ( !HandleFilesInstallation()){ DebugTrace(TRACE_ERROR, (("CDevice::Install: HandleFilesInstallation Failed. Err=0x%x"), GetLastError())); bRet = FALSE; goto Install_return; } // if ( !HandleFilesInstallation()) } // else(IsMigration()) // // We are successfully finished // bRet = TRUE; Install_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::Install: Leaving... Ret=0x%x\n"), bRet)); return bRet; } DWORD CDevice::Remove( PSP_REMOVEDEVICE_PARAMS lprdp ) /*++ Routine Description: Remove method which is called when device is being removed Arguments: Return Value: Side effects: --*/ { CString csUninstallSection; CString csInf; CString csSubClass; DWORD dwCapabilities; PVOID pvContext; HKEY hkDrv; HKEY hkRun; GUID Guid; BOOL bIsServiceStopped; BOOL bIsSti; BOOL bSetParamRet; PSP_FILE_CALLBACK SavedCallback; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; SP_DEVINSTALL_PARAMS DeviceInstallParams; DWORD dwReturn; LPTSTR pSec; DebugTrace(TRACE_PROC_ENTER,(("CDevice::Remove: Enter... \r\n"))); // // Initialize local. // pvContext = NULL; hkDrv = NULL; hkRun = NULL; bSetParamRet = FALSE; SavedCallback = NULL; dwReturn = NO_ERROR; Guid = GUID_DEVCLASS_IMAGE; bIsServiceStopped = FALSE; bIsSti = FALSE; memset(&DeviceInstallParams, 0, sizeof(DeviceInstallParams)); memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData)); // // NT setup inconsistently set this bit , disable for now // #if SETUP_PROBLEM if (!(lprdp->Scope & DI_REMOVEDEVICE_GLOBAL)) { goto Remove_return; } #endif // // The name of the uninstall section was stored during installation // if(IsInterfaceOnlyDevice()){ DebugTrace(TRACE_STATUS,(("CDevice::Remove: This is Interface-only device.\r\n"))); // // Get interface from index. // spDevInterfaceData.cbSize = sizeof(spDevInterfaceData); if(!SetupDiEnumDeviceInterfaces(m_hDevInfo, NULL, &Guid, m_dwInterfaceIndex, &spDevInterfaceData)){ DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiEnumDeviceInterfaces() failed. Err=0x%x \r\n"), GetLastError())); dwReturn = ERROR_NO_DEFAULT_DEVICE_INTERFACE; goto Remove_return; } // // Create interface reg-key. // hkDrv = SetupDiOpenDeviceInterfaceRegKey(m_hDevInfo, &spDevInterfaceData, 0, KEY_READ); } else { // if(IsInterfaceOnlyDevice()) DebugTrace(TRACE_STATUS,(("CDevice::Remove: This is devnode device.\r\n"))); hkDrv = SetupDiOpenDevRegKey(m_hDevInfo, m_pspDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); } // if(IsInterfaceOnlyDevice()) if (hkDrv == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR,(("CDevice::Remove: Invalid device/interface regkey handle. Err=0x%x \r\n"), GetLastError())); dwReturn = ERROR_KEY_DOES_NOT_EXIST; goto Remove_return; } // // Retrieve the name of the .INF File // csUninstallSection.Load (hkDrv, UNINSTALLSECTION); csInf.Load (hkDrv, INFPATH); csSubClass.Load(hkDrv, SUBCLASS); GetDwordFromRegistry(hkDrv, CAPABILITIES, &dwCapabilities); // // See if we need STI/WIA specific operation. // if( (!csSubClass.IsEmpty()) && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) ) { // // This is STI/WIA device. // bIsSti = TRUE; // // Delete "Scanner and Camera Wizard" menu. // if( (dwCapabilities & STI_GENCAP_WIA) && (m_dwNumberOfWiaDevice <= 1) ) { DeleteWiaShortcut(); // // remove following key for performance improvement. // if(ERROR_SUCCESS != RegDeleteKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT)){ DebugTrace(TRACE_ERROR,(("CDevice::Remove: RegDeleteKey() failed. Err=0x%x. \r\n"), GetLastError())); } // if(ERROR_SUCCESS != RegDeleteKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT)) } // if( (dwCapabilities & STI_GENCAP_WIA) // // If this is the last STI/WIA device, set WIA service as Manual. // if(m_dwNumberOfStiDevice <= 1){ HKEY hkeyTemp; DebugTrace(TRACE_STATUS,(("CDevice::Remove: Last WIA device being removed. Set WIA service as MANUAL.\r\n"))); // // No more still image devices -- change service to Manual start // // StopWiaService(); SetServiceStart(STI_SERVICE_NAME, SERVICE_DEMAND_START); bIsServiceStopped = TRUE; // // // Also remove shell's flag about WIA device presence, this should be portable // to NT // if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun) == 0) { RegDeleteValue (hkRun, REGSTR_VAL_WIA_PRESENT); RegCloseKey(hkRun); hkRun = NULL; } // if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun) == 0) } // if(m_dwNumberOfStiDevice <= 1) } // if (m_dwNumberOfDevice <= 1) // // Operaion succeeded. // dwReturn = NO_ERROR; Remove_return: if(IsInterfaceOnlyDevice()){ // // Delete interface resigtry key. // if(!SetupDiDeleteDeviceInterfaceRegKey(m_hDevInfo, &spDevInterfaceData, 0)){ DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiDeleteDeviceInterfaceRegKey failed. Err=0x%x \r\n"), GetLastError())); } // if(!SetupDiDeleteDeviceInterfaceRegKey(m_hDevInfo, &spDevInterfaceData, 0)) // // Remove the interface. // if(!SetupDiRemoveDeviceInterface(m_hDevInfo, &spDevInterfaceData)){ DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiRemoveDeviceInterface failed. Err=0x%x \r\n"), GetLastError())); } // if(!SetupDiRemoveDeviceInterface(m_hDevInfo, &spDevInterfaceData)) } else { // if(IsInterfaceOnlyDevice()) // // Delete device resigtry key. // SetupDiDeleteDevRegKey (m_hDevInfo, m_pspDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_BOTH); if(NO_ERROR == dwReturn){ // // Remove the device node anyway. // if(!SetupDiRemoveDevice(m_hDevInfo, m_pspDevInfoData)){ DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiRemoveDevice failed. Err=0x%x \r\n"), GetLastError())); // // Failed to remove device instance from system. Let default installer do that. // dwReturn = ERROR_DI_DO_DEFAULT; } // if(!SetupDiRemoveDevice(m_hDevInfo, m_pspDevInfoData)) } // if(ERROR_DI_DO_DEFAULT != dwReturn) } // else (IsInterfaceOnlyDevice()) // // Notify WIA service device removal // if(bIsSti){ WiaDeviceEnum(); } // if(TRUE == bIsSti) // // Clean up. // if(IS_VALID_HANDLE(hkDrv)){ RegCloseKey (hkDrv); hkDrv = NULL; } if(IS_VALID_HANDLE(hkRun)){ RegCloseKey (hkRun); hkRun = NULL; } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::Remove: Leaving... Ret=0x%x\n"), dwReturn)); return dwReturn; } BOOL CDevice::PreprocessInf( VOID ) { BOOL bRet; HINF hInf; CString csCapabilities; CString csDeviceType; CString csDeviceSubType; CString csDriverDescription; DebugTrace(TRACE_PROC_ENTER,(("CDevice::PreprocessInf: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; hInf = INVALID_HANDLE_VALUE; // // Check if INF has already been proceeded. // if(m_bInfProceeded){ DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: INF is already processed. \r\n"))); bRet = TRUE; goto ProcessInf_return; } // // Get Inf file/section name. // if( m_csInf.IsEmpty() || m_csInstallSection.IsEmpty()){ GetInfInforamtion(); } // if( m_csInf.IsEmpty() || m_csInstallSection.IsEmpty()) // // Open INF file. // hInf = SetupOpenInfFile(m_csInf, NULL, INF_STYLE_WIN4, NULL); if(!IS_VALID_HANDLE(hInf)){ DebugTrace(TRACE_ERROR, (("CDevice::PreprocessInf: Unable to open INF(%ws). Error = 0x%x.\r\n"),m_csInf, GetLastError())); bRet = FALSE; goto ProcessInf_return; } // if(!IS_VALID_HANDLE(hInf)) // // Check if WiaSection entry exists. // m_csWiaSection.Load (hInf, m_csInstallSection, WIASECTION); if(!m_csWiaSection.IsEmpty()){ DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: WiaSection exists. Acquire all informaiton from WiaSection..\r\n"))); // // Install interface from WiaSection for MFP device. // m_csInstallSection = m_csWiaSection; m_bInterfaceOnly = TRUE; } // if(!m_csWiaSection.IsEmpty()) // // Get all information required for installation from inf file. // m_csSubClass.Load (hInf, m_csInstallSection, SUBCLASS); m_csUSDClass.Load (hInf, m_csInstallSection, USDCLASS); m_csEventSection.Load (hInf, m_csInstallSection, EVENTS); m_csConnection.Load (hInf, m_csInstallSection, CONNECTION); m_csIcmProfile.Load (hInf, m_csInstallSection, ICMPROFILES); m_csPropPages.Load (hInf, m_csInstallSection, PROPERTYPAGES); m_csDataSection.Load (hInf, m_csInstallSection, DEVICESECTION); m_csUninstallSection.Load (hInf, m_csInstallSection, UNINSTALLSECTION); m_csPortSelect.Load (hInf, m_csInstallSection, PORTSELECT); if(!IsMigration()){ csDriverDescription.Load(hInf, m_csInstallSection, DESCRIPTION); if(!csDriverDescription.IsEmpty()){ m_csDriverDescription = csDriverDescription; if(TRUE != NameDefaultUniqueName()){ // // Unable to generate FriendlyName. // bRet = FALSE; goto ProcessInf_return; } // if(TRUE != NameDefaultUniqueName()) } // if(!m_csDriverDescription.IsEmpty()) } // if(!IsMigration()) csCapabilities.Load (hInf, m_csInstallSection, CAPABILITIES); csDeviceType.Load (hInf, m_csInstallSection, DEVICETYPE); csDeviceSubType.Load (hInf, m_csInstallSection, DEVICESUBTYPE); m_dwCapabilities = csCapabilities.Decode(); m_dwDeviceType = csDeviceType.Decode(); m_dwDeviceSubType = csDeviceSubType.Decode(); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: --------------- INF parameters --------------- \r\n"))); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Description : %ws\n"), (LPTSTR)m_csDriverDescription)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: SubClass : %ws\n"), (LPTSTR)m_csSubClass)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: USDClass : %ws\n"), (LPTSTR)m_csUSDClass)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: EventSection : %ws\n"), (LPTSTR)m_csEventSection)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Connection : %ws\n"), (LPTSTR)m_csConnection)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: IcmProfile : %ws\n"), (LPTSTR)m_csIcmProfile)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: PropPages : %ws\n"), (LPTSTR)m_csPropPages)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DataSection : %ws\n"), (LPTSTR)m_csDataSection)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: UninstallSection : %ws\n"), (LPTSTR)m_csUninstallSection)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Capabilities : 0x%x\n"), m_dwCapabilities)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DeviceType : 0x%x\n"), m_dwDeviceType)); DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DeviceSubType : 0x%x\n"), m_dwDeviceSubType)); // // Set video device flag if applicable. // if(StiDeviceTypeStreamingVideo == m_dwDeviceType){ DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: This is video device.\r\n"))); m_bVideoDevice = TRUE; } else { m_bVideoDevice = FALSE; } // // Operation succeeded. // bRet = TRUE; m_bInfProceeded = TRUE; ProcessInf_return: if(IS_VALID_HANDLE(hInf)){ SetupCloseInfFile(hInf); hInf = INVALID_HANDLE_VALUE; } // if(IS_VALID_HANDLE(hInf)) DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PreprocessInf: Leaving... Ret=0x%x \r\n"), bRet)); return bRet; } // CDevice::PreprocessInf() BOOL CDevice::PreInstall( VOID ) { BOOL bRet; HKEY hkDrv; GUID Guid; HDEVINFO hDevInfo; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData; BOOL bUseDefaultDevInfoSet; DWORD dwRequiredSize; DebugTrace(TRACE_PROC_ENTER,(("CDevice::PreInstall: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; // // Get all INF parameter. // if(!PreprocessInf()){ DebugTrace(TRACE_ERROR,(("CDevice::PreInstall: ERROR!! Unable to process INF.\r\n"))); bRet = FALSE; goto PreInstall_return; } /************************************** if(!IsInterfaceOnlyDevice()){ // // Register device if it's getting manually installed and not "interface-only" device.. // if(!IsPnpDevice()){ if (!SetupDiRegisterDeviceInfo(m_hDevInfo, m_pspDevInfoData, 0, NULL, NULL, NULL)) { DebugTrace(TRACE_ERROR,(("CDevice::PreInstall: SetupDiRegisterDeviceInfo failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto PreInstall_return; } } // if(!IsPnpDevice()) } // if(IsInterfaceOnlyDevice()) **************************************/ // // Clean up. // // // Operation succeeded. // bRet = TRUE; PreInstall_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PreInstall: Leaving... Ret=0x%x.\r\n"), bRet)); return bRet; } BOOL CDevice::PostInstall( BOOL bSucceeded ) { BOOL bRet; HKEY hkRun; HKEY hkDrv; DWORD dwFlagPresent; CString csInfFilename; CString csInfSection; GUID Guid; HKEY hkNameStore; DebugTrace(TRACE_PROC_ENTER,(("CDevice::PostInstall: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; hkRun = NULL; dwFlagPresent = 1; Guid = GUID_DEVCLASS_IMAGE; hkNameStore = (HKEY)INVALID_HANDLE_VALUE; if(IsFeatureInstallation()){ // // This is a "feature" added to other class devnode and being installed by co-isntaller. // Need to do actual installation here only for "feature", manual installed device would // be installed through wizard. (final.cpp) // bRet = Install(); if(FALSE == bRet){ DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: device interface registry key creation failed. \r\n"))); bSucceeded = FALSE; } //if(FALSE == bRet) } // if(IsFeatureInstallation()) if(!bSucceeded){ HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; DWORD dwIndex; // // Installation failed. Do clean up. // DebugTrace(TRACE_STATUS,(("CDevice::PostInstall: Installation failed. Do clean up.\r\n"))); // // Delete craeted interface if any. // if(IsInterfaceOnlyDevice()){ hDevInfo = GetDeviceInterfaceIndex(m_csDeviceID, &dwIndex); if(IS_VALID_HANDLE(hDevInfo)){ spDevInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &Guid, dwIndex, &spDevInterfaceData)){ // // Created Interface is found. Delete it... // DebugTrace(TRACE_STATUS,(("CDevice::PostInstall: Deleting created interface for %ws.\r\n"), (LPTSTR)m_csFriendlyName)); if(!SetupDiRemoveDeviceInterface(hDevInfo, &spDevInterfaceData)){ DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! Unable to delete interface for %ws. Err=0x%x\n"), m_csFriendlyName, GetLastError())); } } // if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &Guid, dwIndex, &spDevInterfaceData)) // // Destroy created DevInfoSet. // SetupDiDestroyDeviceInfoList(hDevInfo); } // if(NULL != hDevInfo) } // if(IsInterfaceOnlyDevice()) bRet = TRUE; goto PostInstall_return; } // if(!bSucceeded) // // Save all Inf parameters to registry. // if(!UpdateDeviceRegistry()){ DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! UpdateDeviceRegistry() failed. \r\n"))); } // // Do WIA/STI device only process. // if( (!m_csSubClass.IsEmpty()) && (0 == MyStrCmpi(m_csSubClass, STILL_IMAGE)) ) { HKEY hkeyTemp; // // Change service to AUTO start. // SetServiceStart(STI_SERVICE_NAME, SERVICE_AUTO_START); // // Start WIA service. // if(!StartWiaService()){ // DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! Unable to start WIA service.\r\n"))); } // // Create "Scanner and Camera Wizard" menu if WIA. // if(m_dwCapabilities & STI_GENCAP_WIA){ CreateWiaShortcut(); // // Add following value upon device arrival for performance improvement. // if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT, &hkeyTemp)) { RegSetValue (hkeyTemp, NULL, REG_SZ, REGSTR_VAL_WIASHEXT, lstrlen(REGSTR_VAL_WIASHEXT) * sizeof(TCHAR)); RegCloseKey(hkeyTemp); hkeyTemp = NULL; } else { DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! RegOpenKey(WIASHEXT) failed. Err=0x%x \r\n"), GetLastError())); } // if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun)) } // if(m_dwCapabilities & STI_GENCAP_WIA) // // Also add shell's flag about WIA device presence, this should be portable // to NT // if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun)) { RegDeleteValue (hkRun, REGSTR_VAL_WIA_PRESENT); RegSetValueEx (hkRun, REGSTR_VAL_WIA_PRESENT, 0, REG_DWORD, (LPBYTE)&dwFlagPresent, sizeof(DWORD)); } else { DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! RegOpenKey() failed. Err=0x%x \r\n"), GetLastError())); } // if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun)) // // Notify WIA service device arrival // WiaDeviceEnum(); } // if(!lstrcmpi(m_csSubClass, STILL_IMAGE)) // // ICM support // ProcessICMProfiles(); // // Register interface name of Videoo device. // bRet = TRUE; PostInstall_return: // // Clean up. // if(NULL != hkRun){ RegCloseKey(hkRun); } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PostInstall: Leaving... Ret=0x%x.\r\n"), bRet)); return bRet; } // CDevice::PostInstall() BOOL CDevice::HandleFilesInstallation( VOID ) /*++ Routine Description: Arguments: Return Value: Side effects: --*/ { BOOL bRet; BOOL bSetParamRet; PSP_FILE_CALLBACK pSavedCallback; PVOID pvContext; SP_DEVINSTALL_PARAMS spDeviceInstallParams; DebugTrace(TRACE_PROC_ENTER,(("CDevice::HandleFilesInstallation: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; bSetParamRet = FALSE; pvContext = NULL; pSavedCallback = NULL; memset(&spDeviceInstallParams, 0, sizeof(spDeviceInstallParams)); // // Get device install parameter. // spDeviceInstallParams.cbSize = sizeof (SP_DEVINSTALL_PARAMS); if (!SetupDiGetDeviceInstallParams (m_hDevInfo, m_pspDevInfoData, &spDeviceInstallParams)) { DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiGetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError())); bRet = FALSE; goto HandleFilesInstallation_return; } // // Modify device installation parameters to have custom callback // pvContext = SetupInitDefaultQueueCallbackEx(NULL, (HWND)((spDeviceInstallParams.Flags & DI_QUIETINSTALL) ?INVALID_HANDLE_VALUE : NULL), 0, 0, NULL); if(NULL == pvContext){ DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupInitDefaultQueueCallbackEx() failed. Err=0x%x.\r\n"), GetLastError())); bRet = FALSE; goto HandleFilesInstallation_return; } // if(NULL == pvContext) pSavedCallback = spDeviceInstallParams.InstallMsgHandler; spDeviceInstallParams.InstallMsgHandler = StiInstallCallback; spDeviceInstallParams.InstallMsgHandlerContext = pvContext; bSetParamRet = SetupDiSetDeviceInstallParams (m_hDevInfo, m_pspDevInfoData, &spDeviceInstallParams); if(FALSE == bSetParamRet){ DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError())); bRet = FALSE; goto HandleFilesInstallation_return; } // if(FALSE == bSetParamRet) // // Let the default installer do its job. // if(IsInterfaceOnlyDevice()){ bRet = CreateDeviceInterfaceAndInstall(); } else { bRet = SetupDiInstallDevice(m_hDevInfo, m_pspDevInfoData); } if(FALSE == bRet){ DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiInstallDevice() failed. Err=0x%x.\r\n"), GetLastError())); bRet = FALSE; goto HandleFilesInstallation_return; } // if(FALSE == bSetParamRet) // // Terminate defaule queue callback // SetupTermDefaultQueueCallback(pvContext); // // Cleanup. // if (bSetParamRet) { spDeviceInstallParams.InstallMsgHandler = pSavedCallback; SetupDiSetDeviceInstallParams (m_hDevInfo, m_pspDevInfoData, &spDeviceInstallParams); } HandleFilesInstallation_return: DebugTrace(TRACE_PROC_LEAVE,(("CDevice::HandleFilesInstallation: Leaving... Ret=0x%x.\r\n"), bRet)); return bRet; } // CDevice::HandleFilesInstallation() BOOL CDevice::UpdateDeviceRegistry( VOID ) { BOOL bRet; HKEY hkDrv; DWORD dwConnectionType; HINF hInf; DebugTrace(TRACE_PROC_ENTER,(("CDevice::UpdateDeviceRegistry: Enter... \r\n"))); // // Initialize Local. // bRet = FALSE; hkDrv = NULL; dwConnectionType = STI_HW_CONFIG_UNKNOWN; // // Open INF. // hInf = SetupOpenInfFile(m_csInf, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR, (("CDevice::UpdateDeviceRegistry: Unable to open INF(%ws). Error = 0x%x.\r\n"),m_csInf, GetLastError())); bRet = FALSE; goto UpdateDeviceRegistry_return; } // if (hInf == INVALID_HANDLE_VALUE) // // Create device registry key. // if(IsInterfaceOnlyDevice()){ DebugTrace(TRACE_STATUS,(("CDevice::UpdateDeviceRegistry: This is Interface-only device.\r\n"))); // // Create interface reg-key. // hkDrv = m_hkInterfaceRegistry; } else { // if(IsInterfaceOnlyDevice()) DebugTrace(TRACE_STATUS,(("CDevice::UpdateDeviceRegistry: This is devnode device.\r\n"))); hkDrv = SetupDiCreateDevRegKey(m_hDevInfo, m_pspDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); } // if(IsInterfaceOnlyDevice()) if(hkDrv == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR,(("CDevice::UpdateDeviceRegistry: ERROR!! SetupDiCreateDevRegKey() failed. Err=0x%x.\r\n"), GetLastError())); bRet = FALSE; goto UpdateDeviceRegistry_return; } //if(hkDrv == INVALID_HANDLE_VALUE) // // Save INF parameters to registry. // if(m_csPort.IsEmpty()){ if(m_bInterfaceOnly){ // // If PortName doesn't exist for interface-only device, then use symbolic link as CraeteFile name. // m_csSymbolicLink.Store(hkDrv, CREATEFILENAME); } //if(m_bInterfaceOnly) } else { // if(m_csPort.IsEmpty()) m_csPort.Store(hkDrv, CREATEFILENAME); } // if(m_csPort.IsEmpty()) m_csSubClass.Store(hkDrv, SUBCLASS); m_csUSDClass.Store(hkDrv, USDCLASS); m_csVendor.Store(hkDrv, VENDOR); m_csFriendlyName.Store(hkDrv, FRIENDLYNAME); m_csUninstallSection.Store(hkDrv, UNINSTALLSECTION); m_csPropPages.Store(hkDrv, PROPERTYPAGES); m_csIcmProfile.Store(hkDrv, ICMPROFILES); m_csDeviceID.Store(hkDrv, REGSTR_VAL_DEVICE_ID); m_csPortSelect.Store (hkDrv, PORTSELECT); if(IsInterfaceOnlyDevice()){ m_csInf.Store(hkDrv, INFPATH); m_csInstallSection.Store(hkDrv, INFSECTION); m_csDriverDescription.Store(hkDrv, DRIVERDESC); } // if(IsInterfaceOnlyDevice()) // // Save DWORD values. // RegSetValueEx(hkDrv, CAPABILITIES, 0, REG_DWORD, (LPBYTE) &m_dwCapabilities, sizeof(m_dwCapabilities)); RegSetValueEx(hkDrv, DEVICETYPE, 0, REG_DWORD, (LPBYTE) &m_dwDeviceType, sizeof(m_dwDeviceType)); RegSetValueEx(hkDrv, DEVICESUBTYPE, 0, REG_DWORD, (LPBYTE) &m_dwDeviceSubType, sizeof(m_dwDeviceSubType)); RegSetValueEx(hkDrv, ISPNP, 0, REG_DWORD, (LPBYTE) &m_bIsPnP, sizeof(m_bIsPnP)); // // Set HardwareConfig. (= Connection) // if(!m_csConnection.IsEmpty()){ m_csConnection.Store (hkDrv, CONNECTION); if(_tcsicmp(m_csConnection, SERIAL) == 0 ){ dwConnectionType = STI_HW_CONFIG_SERIAL; } else if(_tcsicmp(m_csConnection, PARALLEL) == 0 ){ dwConnectionType = STI_HW_CONFIG_PARALLEL; } if (dwConnectionType != STI_HW_CONFIG_UNKNOWN) { RegSetValueEx(hkDrv, REGSTR_VAL_HARDWARE, 0, REG_DWORD, (LPBYTE) &dwConnectionType, sizeof(dwConnectionType)); } } // if(!m_csConneciton.IsEmpty()) // // Process DeviceData section. // ProcessDataSection(hInf, hkDrv); // // Process Event section. // ProcessEventsSection(hInf, hkDrv); // // Create registry key for video key if applicable. // ProcessVideoDevice(hkDrv); // // Operation succeeded. // bRet = TRUE; UpdateDeviceRegistry_return: // // Cleanup. // if(hkDrv != INVALID_HANDLE_VALUE){ RegCloseKey(hkDrv); m_hkInterfaceRegistry = NULL; } if(hInf != INVALID_HANDLE_VALUE){ SetupCloseInfFile(hInf); } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::UpdateDeviceRegistry: Leaving... Ret=0x%x.\r\n"), bRet)); return bRet; } // CDevice::UpdateDeviceRegistry() VOID CDevice::ProcessVideoDevice( HKEY hkDrv ) { GUID Guid; HKEY hkDeviceData; TCHAR Buffer[1024]; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetail; DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessVideoDevice: Enter... \r\n"))); // // Initialize local. // Guid = KSCATEGORY_CAPTURE; pspDevInterfaceDetail = NULL; hkDeviceData = NULL; memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData)); memset(Buffer, 0, sizeof(Buffer)); // // This is only for video devices. // if (!m_bVideoDevice) { DebugTrace(TRACE_STATUS,(("CDevice::ProcessVideoDevice: This is not a video device. Do nothing.\r\n"))); goto ProcessVideoDevice_return; } // // Use "AUTO" as dummy CreatFile name for Video devices. // RegSetValueEx( hkDrv, CREATEFILENAME, 0, REG_SZ, (LPBYTE)AUTO, (lstrlen(AUTO)+1)*sizeof(TCHAR) ); // // Get device interface data of installing Video device. // spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (!SetupDiEnumDeviceInterfaces (m_hDevInfo, m_pspDevInfoData, &Guid, 0, &spDevInterfaceData ) ) { DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!!SetupDiEnumDeviceInterfaces failed. Err=0x%x \r\n"), GetLastError())); goto ProcessVideoDevice_return; } // // Get detailed data of acquired interface. // pspDevInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buffer; pspDevInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if (!SetupDiGetDeviceInterfaceDetail (m_hDevInfo, &spDevInterfaceData, pspDevInterfaceDetail, sizeof(Buffer) - sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA), NULL, NULL) ) { DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!!SetupDiGetDeviceInterfaceDetail failed. Err=0x%x \r\n"), GetLastError())); goto ProcessVideoDevice_return; } // // We got the device path, now write it to registry // if (ERROR_SUCCESS != RegOpenKey(hkDrv, DEVICESECTION, &hkDeviceData)) { DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!! Unable to open DeviceData key. Err=0x%x \r\n"), GetLastError())); goto ProcessVideoDevice_return; } RegSetValueEx(hkDeviceData, VIDEO_PATH_ID, 0, REG_SZ, (LPBYTE)pspDevInterfaceDetail->DevicePath, (lstrlen(pspDevInterfaceDetail->DevicePath)+1)*sizeof(TCHAR) ); ProcessVideoDevice_return: // // Cleanup. // if(NULL != hkDeviceData){ RegCloseKey(hkDeviceData); } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessVideoDevice: Leaving... Ret=VOID.\r\n"))); return; } // CDevice::ProcessVideoDevice() VOID CDevice::ProcessEventsSection( HINF hInf, HKEY hkDrv ) /*++ Routine Description: Arguments: Return Value: Side effects: --*/ { CString csFriendlyName; CString csRegisteredApp; CString csGuid; HKEY hkEvents; HKEY hkEventPod; INFCONTEXT InfContext; UINT uiLineIndex = 0; BOOL fRet = TRUE; BOOL fLooping = TRUE; TCHAR pKeyName[LINE_LEN ]; TCHAR pField [MAX_INF_STRING_LENGTH]; TCHAR pTypeField[LINE_LEN]; DWORD dwKeySize = LINE_LEN; DWORD dwFieldSize = MAX_INF_STRING_LENGTH; DWORD dwError = 0; DWORD dwFieldIndex = 0; DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessEventsSection: Enter... \r\n"))); if (!m_csEventSection.IsEmpty()) { // First create device data subkey dwError = RegCreateKey(hkDrv, EVENTS, &hkEvents); if ( NOERROR == dwError ) { fLooping = SetupFindFirstLine(hInf, (LPCTSTR) m_csEventSection, NULL, &InfContext ); while (fLooping) { ::ZeroMemory(pKeyName, sizeof(pKeyName)); ::ZeroMemory(pField, sizeof(pField)); ::ZeroMemory(pTypeField, sizeof(pTypeField) ); // Get key name as zero-based indexed field dwFieldIndex = 0; dwKeySize = sizeof(pKeyName) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, dwFieldIndex, pKeyName, dwKeySize, NULL); dwError = ::GetLastError(); if (!fRet) { // Didn't get key name - move to the next DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get key name. Error=0x%x. \r\n"), dwError)); fLooping = SetupFindNextLine(&InfContext,&InfContext); continue; } // Get friendly name field dwFieldIndex = 1; dwFieldSize = sizeof(pField) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, dwFieldIndex, pField, dwFieldSize, NULL); dwError = ::GetLastError(); if (!fRet ) { // Didn't get name - move to the next DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError)); fLooping = SetupFindNextLine(&InfContext,&InfContext); continue; } csFriendlyName = pField; // Get GUID field dwFieldIndex = 2; dwFieldSize = sizeof(pField) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, dwFieldIndex, pField, dwFieldSize, NULL); dwError = ::GetLastError(); if (!fRet ) { // Didn't get GUID - move to the next line DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError)); fLooping = SetupFindNextLine(&InfContext,&InfContext); continue; } csGuid = pField; // Get registered app field dwFieldIndex = 3; dwFieldSize = sizeof(pField) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, 3, pField, dwFieldSize, NULL); dwError = ::GetLastError(); if (fRet ) { DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError)); csRegisteredApp = pField; } else { // Didn't get key type - use widlcard by default csRegisteredApp = TEXT("*"); } // Now only if we have all needed values - save to the registry if (RegCreateKey(hkEvents, pKeyName, &hkEventPod) == NO_ERROR) { // Event friendly name store as default value csFriendlyName.Store (hkEventPod, TEXT("")); csGuid.Store (hkEventPod, SZ_GUID); csRegisteredApp.Store (hkEventPod, LAUNCH_APP); RegCloseKey (hkEventPod); } else { // Couldn't create event key - bad DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Unable to create RegKey. Error=0x%x.\r\n"), GetLastError())); } // Move to the next line finally fLooping = SetupFindNextLine(&InfContext,&InfContext); } RegCloseKey (hkEvents); } else { DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Unable to create event RegKey. Error=0x%x.\r\n"), GetLastError())); } } // ProcessEventsSection_return: // // Cleanup. // DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessEventsSection: Leaving... Ret=VOID.\r\n"))); return; } // CDevice::ProcessEventsSection() VOID CDevice::ProcessDataSection( HINF hInf, HKEY hkDrv ) /*++ Routine Description: Arguments: Return Value: Side effects: --*/ { CString csTempValue; HKEY hkDeviceData; INFCONTEXT InfContext; UINT uiLineIndex = 0; BOOL fRet = TRUE; BOOL fLooping = TRUE; TCHAR pKeyName[LINE_LEN ]; TCHAR pField [MAX_INF_STRING_LENGTH]; TCHAR pTypeField[LINE_LEN]; // Sizes are in characters DWORD dwKeySize = LINE_LEN; DWORD dwFieldSize = MAX_INF_STRING_LENGTH; DWORD dwError = 0; DWORD dwFieldIndex = 0; DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessDataSection: Enter... \r\n"))); if (!m_csDataSection.IsEmpty()) { // First create device data subkey dwError = RegCreateKey(hkDrv, DEVICESECTION, &hkDeviceData); if ( NOERROR == dwError ) { // Seek to the first line of the section fLooping = SetupFindFirstLine(hInf, (LPCTSTR) m_csDataSection, NULL, &InfContext); while (fLooping) { dwKeySize = sizeof(pKeyName) / sizeof(TCHAR); ::ZeroMemory(pKeyName, sizeof(pKeyName)); ::ZeroMemory(pField, sizeof(pField)); ::ZeroMemory(pTypeField, sizeof(pTypeField) ); dwFieldIndex = 0; // Get key name as zero-indexed field fRet = SetupGetStringField(&InfContext, dwFieldIndex, pKeyName, dwKeySize, &dwKeySize); dwError = ::GetLastError(); if (!fRet) { // Didn't get key name - move to the next DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: Failed to get key name. Error = 0x%x.\r\n"),dwError)); fLooping = SetupFindNextLine(&InfContext,&InfContext); continue; } // Get value field dwFieldIndex = 1; dwFieldSize = sizeof(pField) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, dwFieldIndex, pField, dwFieldSize, NULL); dwError = ::GetLastError(); if (!fRet ) { // Didn't get key name - move to the next DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: Failed to get field [%d]. Error = 0x%x.\r\n"),dwFieldIndex, dwError)); fLooping = SetupFindNextLine(&InfContext,&InfContext); continue; } csTempValue = pField; // Get value field *pTypeField = TEXT('\0'); dwFieldIndex = 2; dwFieldSize = sizeof(pTypeField) / sizeof(TCHAR); fRet = SetupGetStringField(&InfContext, dwFieldIndex, pTypeField, dwFieldSize, NULL); dwError = ::GetLastError(); if (!fRet ) { // Didn't get key type - assume string *pTypeField = TEXT('\0'); } // Now we have both type and value - save it in the registry csTempValue.Store (hkDeviceData, pKeyName,pTypeField ); // Move to the next line finally fLooping = SetupFindNextLine(&InfContext,&InfContext); } // // Process migrating DeviceData section. // MigrateDeviceData(hkDeviceData, m_pExtraDeviceData, ""); // Now clean up RegCloseKey (hkDeviceData); } else { // if ( NOERROR == dwError ) DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: ERROR!! Unable to create DataSection RegKey. Error = 0x%x.\r\n"), dwError)); } // if ( NOERROR == dwError ) } // if (!m_csDataSection.IsEmpty()) // ProcessDataSection_return: // // Cleanup. // DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessDataSection: Leaving... Ret=VOID.\r\n"))); return; } // CDevice::ProcessDataSection() VOID CDevice::ProcessICMProfiles( VOID ) /*++ Routine Description: Arguments: Return Value: Side effects: --*/ { DWORD Idx; CStringArray csaICMProfiles; TCHAR szAnsiName[STI_MAX_INTERNAL_NAME_LENGTH]; DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessICMProfiles: Enter... \r\n"))); // // Initialize Local. // Idx = 0; memset(szAnsiName, 0, sizeof(szAnsiName)); // // If section doesn't exist, just return. // if(m_csIcmProfile.IsEmpty()){ goto ProcessICMProfiles_return; } // // Split a line to each token. // csaICMProfiles.Tokenize ((LPTSTR)m_csIcmProfile, FIELD_DELIMETER); // // Process all ICM profiles. // while ((LPTSTR)csaICMProfiles[Idx] != NULL) { DebugTrace(TRACE_STATUS,(("ProcessICMProfiles: Installing ICM profile%d(%ws) for %ws.\r\n"), Idx, (LPTSTR)csaICMProfiles[Idx], (LPTSTR)m_csDeviceID)); // // Install color profile. // if (!InstallColorProfile (NULL, csaICMProfiles[Idx])) { DebugTrace(TRACE_ERROR,(("ProcessICMProfiles: ERROR!! InstallColorProfile failed. Err=0x%x \r\n"), GetLastError())); } // if (!InstallColorProfile (NULL, csaICMProfiles[Idx])) // // Register color profile with installing device. // if (!AssociateColorProfileWithDevice (NULL, csaICMProfiles[Idx], (LPTSTR)m_csDeviceID)) { DebugTrace(TRACE_ERROR,(("ProcessICMProfiles: ERROR!! AssociateColorProfileWithDevice failed. Err=0x%x \r\n"), GetLastError())); } // // Process next device. // Idx++; } // while ((LPTSTR)csaICMProfiles[Idx] != NULL) ProcessICMProfiles_return: return; } // CDevice::ProcessICMProfiles() BOOL CDevice::GetInfInforamtion( VOID ) { BOOL bRet; HINF hInf; SP_DRVINFO_DATA DriverInfoData; PSP_DRVINFO_DETAIL_DATA pDriverInfoDetailData; TCHAR szInfSectionName[MAX_DESCRIPTION]; DWORD dwSize; DWORD dwLastError; DebugTrace(TRACE_PROC_ENTER,(("CDevice::GetInfInforamtion: Enter... \r\n"))); // // Initialize locals. // dwSize = 0; bRet = FALSE; hInf = INVALID_HANDLE_VALUE; dwLastError = ERROR_SUCCESS; pDriverInfoDetailData = NULL; memset (szInfSectionName, 0, sizeof(szInfSectionName)); memset (&DriverInfoData, 0, sizeof(SP_DRVINFO_DATA)); // // Get selected device driver information. // DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); if (!SetupDiGetSelectedDriver(m_hDevInfo, m_pspDevInfoData, &DriverInfoData)) { DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetSelectedDriver Failed. Err=0x%x\r\n"), GetLastError())); bRet = FALSE; goto GetInfInforamtion_return; } // // See required buffer size for driver detailed data. // SetupDiGetDriverInfoDetail(m_hDevInfo, m_pspDevInfoData, &DriverInfoData, NULL, 0, &dwSize); dwLastError = GetLastError(); if(ERROR_INSUFFICIENT_BUFFER != dwLastError){ DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetDriverInfoDetail doesn't return required size.Er=0x%x\r\n"),dwLastError)); bRet = FALSE; goto GetInfInforamtion_return; } // // Allocate required size of buffer for driver detailed data. // pDriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)new char[dwSize]; if(NULL == pDriverInfoDetailData){ DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! Unable to allocate driver detailed info buffer.\r\n"))); bRet = FALSE; goto GetInfInforamtion_return; } // // Initialize allocated buffer. // memset(pDriverInfoDetailData, 0, dwSize); pDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); // // Get detailed data of selected device driver. // if(!SetupDiGetDriverInfoDetail(m_hDevInfo, m_pspDevInfoData, &DriverInfoData, pDriverInfoDetailData, dwSize, NULL) ) { DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetDriverInfoDetail Failed.Er=0x%x\r\n"),GetLastError())); bRet = FALSE; goto GetInfInforamtion_return; } // // Open INF file of selected driver. // hInf = SetupOpenInfFile(pDriverInfoDetailData->InfFileName, NULL, INF_STYLE_WIN4, NULL); if (hInf == INVALID_HANDLE_VALUE) { DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupOpenInfFile Failed.Er=0x%x\r\n"),GetLastError())); bRet = FALSE; goto GetInfInforamtion_return; } // // Get actual INF section name to be installed. // if (!SetupDiGetActualSectionToInstall(hInf, pDriverInfoDetailData->SectionName, szInfSectionName, sizeof(szInfSectionName)/sizeof(TCHAR), NULL, NULL) ) { DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetActualSectionToInstall Failed.Er=0x%x\r\n"),GetLastError())); bRet = FALSE; goto GetInfInforamtion_return; } // // Set Inf section/file name. // m_csInf = pDriverInfoDetailData->InfFileName; m_csInstallSection = szInfSectionName; DebugTrace(TRACE_STATUS,(("CDevice::GetInfInforamtion: INF Filename : %ws\n"),(LPTSTR)m_csInf)); DebugTrace(TRACE_STATUS,(("CDevice::GetInfInforamtion: INF Section name: %ws\n"),(LPTSTR)m_csInstallSection)); // // Operation succeeded. // bRet = TRUE; GetInfInforamtion_return: // // Clean up. // if(INVALID_HANDLE_VALUE != hInf){ SetupCloseInfFile(hInf); } if(NULL != pDriverInfoDetailData){ delete[] pDriverInfoDetailData; } DebugTrace(TRACE_PROC_LEAVE,(("CDevice::GetInfInforamtion: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // CDevice::GetInfInforamtion() VOID CDevice::SetPort( LPTSTR szPortName ) { DebugTrace(TRACE_STATUS,(("CDevice::SetPort: Current Portname=%ws\n"), szPortName)); // // Set PortName. // m_csPort = szPortName; } // CDevice::SetPort() VOID CDevice::SetFriendlyName( LPTSTR szFriendlyName ) // // Note: // Before calling this function, caller has to make sure mutex is acquired. // { HKEY hkNameStore; // // Mutex must have been acquired before this call. // DebugTrace(TRACE_STATUS,(("CDevice::SetFriendlyName: Current CreateFileName=%ws\n"), szFriendlyName)); // // Delete stored entry, create new one. // if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){ HKEY hkTemp; hkTemp = (HKEY)INVALID_HANDLE_VALUE; // // Delete FriendlyName and DeviceId in name store. // RegDeleteKey(hkNameStore, m_csFriendlyName); if(ERROR_SUCCESS == RegCreateKey(hkNameStore, szFriendlyName, &hkTemp)){ RegCloseKey(hkTemp); } // if(ERROR_SUCCESS == RegCreateKey(hkNameStore, szFriendlyName, &hkTemp)) RegCloseKey(hkNameStore); } // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)) // // Set PortName. // m_csFriendlyName = szFriendlyName; } // CDevice::SetPort() VOID CDevice::SetDevnodeSelectCallback( DEVNODESELCALLBACK pfnDevnodeSelCallback ) { DebugTrace(TRACE_STATUS,(("CDevice::SetDevnodeSelectCallback: Current PortselCallback=0x%x\n"), pfnDevnodeSelCallback)); // // Set SetPortselCallBack. // m_pfnDevnodeSelCallback = pfnDevnodeSelCallback; // // This is "interface-only" device. // m_bInterfaceOnly = TRUE; } // CDevice::SetDevnodeSelectCallback() BOOL CDevice::CreateDeviceInterfaceAndInstall( VOID ) { BOOL bRet; HKEY hkDrv; GUID Guid; HDEVINFO hDevInfo; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData; HINF hInf; BOOL bUseDefaultDevInfoSet; DWORD dwRequiredSize; DebugTrace(TRACE_PROC_ENTER,(("CDevice::CreateDeviceInterfaceAndInstall: Enter....\r\n"))); // // Initialize local. // bRet = FALSE; hInf = INVALID_HANDLE_VALUE; hDevInfo = INVALID_HANDLE_VALUE; Guid = GUID_DEVCLASS_IMAGE; bUseDefaultDevInfoSet = TRUE; dwRequiredSize = 0; pspDevInterfaceDetailData = NULL; // // Get devnode to create interface on. // if(NULL != m_pfnDevnodeSelCallback){ if( (FALSE == m_pfnDevnodeSelCallback(m_csPort, &hDevInfo, &spDevInfoData)) || (INVALID_HANDLE_VALUE == hDevInfo) ) { DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: m_pfnDevnodeSelCallback failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // // Devnode selector functions. // bUseDefaultDevInfoSet = FALSE; } else { // if(NULL != m_pfnDevnodeSelCallback) // // Use default device info set if available. // if( (INVALID_HANDLE_VALUE == m_hDevInfo) || (NULL == m_pspDevInfoData) ) { DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Invalid Device info and no m_pfnDevnodeSelCallback.\r\n"))); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } else { hDevInfo = m_hDevInfo; spDevInfoData = *m_pspDevInfoData; } } // if(NULL != m_pfnDevnodeSelCallback) // // Create Interface (SoftDevice). Use FriendlyName ad ref-string. // DebugTrace(TRACE_STATUS,(("CDevice::CreateDeviceInterfaceAndInstall: Creating interface for %ws.\r\n"), (LPTSTR)m_csFriendlyName)); spDevInterfaceData.cbSize = sizeof(spDevInterfaceData); if(!SetupDiCreateDeviceInterface(hDevInfo, &spDevInfoData, &Guid, m_csFriendlyName, 0, &spDevInterfaceData)) { DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiCreateInterface failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // // Get symbolic link of created interface. // SetupDiGetDeviceInterfaceDetail(hDevInfo, &spDevInterfaceData, NULL, 0, &dwRequiredSize, NULL); if(0 == dwRequiredSize){ DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Unable to get required size for InterfaceDetailedData. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // if(0 == dwRequiredSize) pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[dwRequiredSize]; if(NULL == pspDevInterfaceDetailData){ DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Unable to allocate buffer.\r\n"))); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // if(NULL == pspDevInterfaceDetailData) pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if(!SetupDiGetDeviceInterfaceDetail(hDevInfo, &spDevInterfaceData, pspDevInterfaceDetailData, dwRequiredSize, &dwRequiredSize, NULL)) { DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiGetDeviceInterfaceDetail() failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // if(!SetupDiGetDeviceInterfaceDetail( m_csSymbolicLink = pspDevInterfaceDetailData->DevicePath; // // Open INF file handle for registry creation. // hInf = SetupOpenInfFile(m_csInf, NULL, INF_STYLE_WIN4, NULL); if(INVALID_HANDLE_VALUE == hInf){ DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupOpenInfFile failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // if(INVALID_HANDLE_VALUE == hInf) if(!SetupOpenAppendInfFile(NULL, hInf, NULL)){ DebugTrace(TRACE_WARNING,(("CDevice::CreateDeviceInterfaceAndInstall: SetupOpenAppendInfFile() failed. Err=0x%x.\r\n"),GetLastError())); } // if(!SetupOpenAppendInfFile(NULL, hInf, NULL)) // // Create Interface Registry and keep its handle, it's hard to find it later. // m_hkInterfaceRegistry = SetupDiCreateDeviceInterfaceRegKey(hDevInfo, &spDevInterfaceData, 0, KEY_ALL_ACCESS, // NULL, // NULL); hInf, (LPCTSTR)m_csInstallSection); if(INVALID_HANDLE_VALUE == m_hkInterfaceRegistry){ DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiCreateDeviceInterfaceRegKey failed. Err=0x%x.\r\n"),GetLastError())); bRet = FALSE; goto CreateDeviceInterfaceAndInstall_return; } // if(INVALID_HANDLE_VALUE == m_hkInterfaceRegistry) // // Operation succeeded. // bRet = TRUE; CreateDeviceInterfaceAndInstall_return: // // Clean up. // if(INVALID_HANDLE_VALUE != hDevInfo){ if(FALSE == bUseDefaultDevInfoSet){ // // Destroy created DevInfoSet. // SetupDiDestroyDeviceInfoList(hDevInfo); } // if(FALSE == bUseDefaultDevInfoSet) } // if(INVALID_HANDLE_VALUE != hDevInfo) if(INVALID_HANDLE_VALUE != hInf){ SetupCloseInfFile(hInf); } // if(INVALID_HANDLE_VALUE != hInf) if(NULL != pspDevInterfaceDetailData){ delete[] pspDevInterfaceDetailData; } // if(NULL != pspDevInterfaceDetailData) DebugTrace(TRACE_PROC_LEAVE,(("CDevice::CreateDeviceInterfaceAndInstall: Leaving... Ret=0x%x.\r\n"), bRet)); return bRet; } // CDevice::CreateDeviceInterfaceAndInstall() DWORD CDevice::GetPortSelectMode( VOID ) { DWORD dwRet; // // Initialize local. // dwRet = PORTSELMODE_NORMAL; // // Make sure INF is processed. // if(!PreprocessInf()){ DebugTrace(TRACE_ERROR,(("CDevice::GetPortSelectMode: ERROR!! Unable to process INF.\r\n"))); dwRet = PORTSELMODE_NORMAL; goto GetPortSelectMode_return; } // // If "PortSelect" is empty, use default. // if(m_csPortSelect.IsEmpty()){ dwRet = PORTSELMODE_NORMAL; goto GetPortSelectMode_return; } // if(m_csPortSelect.IsEmpty()) // // See if "PortSelect" directive is "no". // if(0 == MyStrCmpi(m_csPortSelect, NO)){ // // Port Selection page should be skipped. // dwRet = PORTSELMODE_SKIP; } else if(0 == MyStrCmpi(m_csPortSelect, MESSAGE1)){ // // System supplied message should be shown. // dwRet = PORTSELMODE_MESSAGE1; } else { // // Unsupported PortSel option. // dwRet = PORTSELMODE_NORMAL; } GetPortSelectMode_return: return dwRet; } // CDevice::GetPortSelectMode() DWORD CDevice::AcquireInstallerMutex( DWORD dwTimeout ) { DWORD dwReturn; // // Initialize local. // dwReturn = ERROR_SUCCESS; if(NULL != m_hMutex){ // // Mutex is already acquired. // DebugTrace(TRACE_WARNING,("WARNING!! AcquireInstallerMutex: Mutex acquired twice.\r\n")); dwReturn = ERROR_SUCCESS; goto AcquireInstallerMutex_return; } // if(INVALID_HANDLE_VALUE != m_hMutex) // // Acquire Mutex. // m_hMutex = CreateMutex(NULL, FALSE, WIAINSTALLERMUTEX); dwReturn = GetLastError(); if(NULL == m_hMutex){ // // CreteMutex() failed. // DebugTrace(TRACE_ERROR,("ERROR!! AcquireInstallerMutex: CraeteMutex() failed. Err=0x%x.\r\n", dwReturn)); goto AcquireInstallerMutex_return; } // if(NULL == hMutex) // // Wait until ownership is acquired. // dwReturn = WaitForSingleObject(m_hMutex, dwTimeout); switch(dwReturn){ case WAIT_ABANDONED: DebugTrace(TRACE_ERROR, ("CDevice::AcquireInstallerMutex: ERROR!! Wait abandoned.\r\n")); break; case WAIT_OBJECT_0: DebugTrace(TRACE_STATUS, ("CDevice::AcquireInstallerMutex: Mutex acquired.\r\n")); dwReturn = ERROR_SUCCESS; break; case WAIT_TIMEOUT: DebugTrace(TRACE_WARNING, ("CDevice::AcquireInstallerMutex: WARNING!! Mutex acquisition timeout.\r\n")); break; default: DebugTrace(TRACE_ERROR, ("CDevice::AcquireInstallerMutex: ERROR!! Unexpected error from WaitForSingleObjecct(). Err=0x%x.\r\n", dwReturn)); break; } // switch(dwReturn) AcquireInstallerMutex_return: DebugTrace(TRACE_PROC_LEAVE,("CDevice::AcquireInstallerMutex: Leaving... Ret=0x%x\n", dwReturn)); return dwReturn; } // CDevice::AcquireInstallerMutex() VOID CDevice::ReleaseInstallerMutex( ) { if(NULL != m_hMutex){ if(!ReleaseMutex(m_hMutex)){ DebugTrace(TRACE_ERROR, ("CDevice::ReleaseInstallerMutex: ERROR!! Releasing mutex which not owned..\r\n")); } // if(!ReleaseMutex(m_hMutex)) CloseHandle(m_hMutex); m_hMutex = NULL; DebugTrace(TRACE_STATUS, ("CDevice::ReleaseInstallerMutex: Mutex released.\r\n")); } // if(NULL != m_hMutex) } // CDevice::ReleaseInstallerMutex() UINT CALLBACK StiInstallCallback ( PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2 ) /*++ Routine Description: StiInstallCallback Callback routine used when calling SetupAPI file copying/installation functions Arguments: Context - our context Notification - notification message Return Value: SetupAPI return code Side effects: None --*/ { UINT uRet = FILEOP_COPY; DebugTrace(TRACE_PROC_ENTER,(("StiInstallCallback: Enter... \r\n"))); // // Initialize local. // uRet = FILEOP_COPY; // // Dispatch notification code. // switch(Notification){ case SPFILENOTIFY_ENDCOPY: { PFILEPATHS pFilePathInfo; HKEY hKey; DWORD dwDisposition; DWORD dwRefCount; DWORD dwType; UINT uSize; LONG Status; uSize = sizeof(dwRefCount); pFilePathInfo = (PFILEPATHS)Param1; DebugTrace(TRACE_STATUS,(("StiInstallCallback:ENDCOPY FileTarget %ws\r\n"), pFilePathInfo->Target)); // // Open HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDlls // Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_SHAREDDLL, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); if(ERROR_SUCCESS != Status) { DebugTrace(TRACE_ERROR,(("StiInstallCallback: RegCreateKeyEx failed. Err=0x%x\r\n"), Status)); break; } // // Retrieve reference count of this file // Status = RegQueryValueEx(hKey, pFilePathInfo->Target, NULL, &dwType, (LPBYTE)&dwRefCount, (LPDWORD)&uSize); if(ERROR_SUCCESS != Status) { // // Value for this file hasn't been created, or error // DebugTrace(TRACE_ERROR,(("StiInstallCallback: Value for Ref-count doesn't exist\r\n"))); dwRefCount = 0; } // // Increment reference count and set value // dwRefCount++; uSize = sizeof(dwRefCount); Status = RegSetValueEx(hKey, pFilePathInfo->Target, NULL, REG_DWORD, (CONST BYTE *)&dwRefCount, uSize); if(ERROR_SUCCESS != Status) { DebugTrace(TRACE_ERROR,(("StiInstallCallback: RegSetValueEx. Err=0x%x.\r\n"), Status)); } DebugTrace(TRACE_STATUS,(("StiInstallCallback: ref-count of %ws is now 0x%x.\r\n"), pFilePathInfo->Target, dwRefCount)); // // Close Registry key // RegCloseKey(hKey); Report(( TEXT("StiInstallCallback:%ws copied.\r\n"), pFilePathInfo->Target)); } // case SPFILENOTIFY_ENDCOPY default: ; } uRet = SetupDefaultQueueCallback(Context, Notification, Param1, Param2); DebugTrace(TRACE_PROC_LEAVE,(("StiInstallCallback: Leaving... Ret=0x%x\n"), uRet)); return uRet; } VOID GetDeviceCount( DWORD *pdwWiaCount, DWORD *pdwStiCount ) /*++ Routine Description: GetDeviceCount Verifes if there is at least one STI device installed in a system Arguments: bWia - TRUE: Count WIA device Return Value: Number of WIA device FALSE --*/ { DWORD dwWiaCount; DWORD dwStiCount; BOOL fRet; CString csSubClass; DWORD dwCapabilities; GUID Guid; UINT Idx; DWORD dwRequired; DWORD dwError; HKEY hkThis; HKEY hkRun; HANDLE hDevInfo; SP_DEVINFO_DATA spDevInfoData; SP_DEVICE_INTERFACE_DATA spDevInterfaceData; DebugTrace(TRACE_PROC_ENTER,(("GetDeviceCount: Enter... \r\n"))); // // Initialize local. // dwWiaCount = 0; dwStiCount = 0; fRet = FALSE; Idx = 0; dwRequired = 0; dwError = 0; hkThis = NULL; hkRun = NULL; hDevInfo = NULL; dwCapabilities = 0; memset(&spDevInfoData, 0, sizeof(spDevInfoData)); memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData)); // // Get WIA class guid. // SetupDiClassGuidsFromName (CLASSNAME, &Guid, sizeof(GUID), &dwRequired); // // Get device info set of all WIA devices (devnode). // hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE ); if (hDevInfo != INVALID_HANDLE_VALUE) { spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA); for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) { #if DEBUG CHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH]; ULONG cbData; fRet = SetupDiGetDeviceRegistryProperty (hDevInfo, &spDevInfoData, SPDRP_DRIVER, NULL, (UCHAR *)szDevDriver, sizeof (szDevDriver), &cbData); DebugTrace(TRACE_STATUS,(("GetDeviceCount: Checking device No%d(%ws)\r\n"), Idx, szDevDriver)); #endif // // Verify device is not being removed // spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); spDevInterfaceData.InterfaceClassGuid = GUID_DEVCLASS_IMAGE; fRet = SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); dwError = GetLastError(); if (fRet) { if (spDevInterfaceData.Flags & SPINT_REMOVED) { continue; } } hkThis = SetupDiOpenDevRegKey(hDevInfo, &spDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ ); if (hkThis != INVALID_HANDLE_VALUE) { csSubClass.Load(hkThis, SUBCLASS); GetDwordFromRegistry(hkThis, CAPABILITIES, &dwCapabilities); DebugTrace(TRACE_STATUS,(("GetDeviceCount: Capabilities=0x%x\n"), dwCapabilities)); RegCloseKey(hkThis); if( (!csSubClass.IsEmpty()) && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) ) { // // STI device found. Increse the counter. // dwStiCount++; if(dwCapabilities & STI_GENCAP_WIA){ // // WIA device found. // dwWiaCount++; } // if(dwCapabilities & STI_GENCAP_WIA){ } // if (!csSubClass.IsEmpty() && !lstrcmpi(csSubClass, STILL_IMAGE)) } // if (hkThis != INVALID_HANDLE_VALUE) } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) SetupDiDestroyDeviceInfoList(hDevInfo); } else { DebugTrace(TRACE_ERROR,(("GetDeviceCount: ERROR!! Unable to get device info set.\r\n"))); } // if (hDevInfo != INVALID_HANDLE_VALUE) // // Get device info set of all WIA devices (interface). // hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE | DIGCF_DEVICEINTERFACE ); if (hDevInfo != INVALID_HANDLE_VALUE) { spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) { DebugTrace(TRACE_STATUS,(("GetDeviceCount: Checking interface No%d.\r\n"), Idx)); // // Verify device is not being removed // if (spDevInterfaceData.Flags & SPINT_REMOVED) { continue; } hkThis = SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &spDevInterfaceData, 0, KEY_READ ); if (hkThis != INVALID_HANDLE_VALUE) { csSubClass.Load(hkThis, SUBCLASS); GetDwordFromRegistry(hkThis, CAPABILITIES, &dwCapabilities); RegCloseKey(hkThis); if( (!csSubClass.IsEmpty()) && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) ) { // // STI device found. Increse the counter. // dwStiCount++; if(dwCapabilities & STI_GENCAP_WIA){ // // WIA device found. // dwWiaCount++; } // if(dwCapabilities & STI_GENCAP_WIA){ } // if (!csSubClass.IsEmpty() && !lstrcmpi(csSubClass, STILL_IMAGE)) } // if (hkThis != INVALID_HANDLE_VALUE) } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) SetupDiDestroyDeviceInfoList(hDevInfo); } else { // if (hDevInfo != INVALID_HANDLE_VALUE) DebugTrace(TRACE_ERROR,(("GetDeviceCount: ERROR!! Unable to get device info set.\r\n"))); } // if (hDevInfo != INVALID_HANDLE_VALUE) // // Copy the result. // *pdwWiaCount = dwWiaCount; *pdwStiCount = dwStiCount; DebugTrace(TRACE_PROC_LEAVE,(("GetDeviceCount: Leaving... STI=0x%x, WIA=0x%x.\r\n"), dwStiCount, dwWiaCount)); return; } // GetDeviceCount() BOOL ExecCommandLine( LPTSTR szCommandLine ) { BOOL bRet; CString csCommandLine; PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si), // cb NULL, // lpReserved; NULL, // lpDesktop; NULL, // lpTitle; 0, // dwX; 0, // dwY; 0, // dwXSize; 0, // dwYSize; 0, // dwXCountChars; 0, // dwYCountChars; 0, // dwFillAttribute; STARTF_FORCEONFEEDBACK, // dwFlags; SW_SHOWNORMAL, // wShowWindow; 0, // cbReserved2; NULL, // lpReserved2; NULL, // hStdInput; NULL, // hStdOutput; NULL // hStdError; }; csCommandLine = szCommandLine; bRet = CreateProcess(NULL, // Application name (LPTSTR)csCommandLine, // Command line NULL, // Process attributes NULL, // Thread attributes FALSE, // Handle inheritance NORMAL_PRIORITY_CLASS, // Creation flags NULL, // Environment NULL, // Current directory &si, &pi); if (bRet) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { DebugTrace(TRACE_ERROR,(("ExecCommandLine: CreateProcess failed. Err=0x%x.\r\n"), GetLastError())); } return bRet; } PPARAM_LIST MigrateDeviceData( HKEY hkDeviceData, PPARAM_LIST pExtraDeviceData, LPSTR pszKeyName ) { BOOL bDone; PPARAM_LIST pCurrent; PPARAM_LIST pReturn; DWORD dwType; DWORD dwSize; PCHAR pOrginalBuffer; CHAR pCopyBuffer[MAX_PATH*3]; CHAR pDataBuffer[MAX_PATH]; DWORD Idx; // // Initialize local. // bDone = FALSE; pCurrent = pExtraDeviceData; pReturn = NULL; // // Loop until it gets "END". // while(!bDone){ if(NULL == pCurrent){ // // Hit the end of list. // bDone = TRUE; pReturn =NULL; continue; } // if(NULL == pTemp) // // If "KeyName = END" is found, return. // if( (CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam1, -1,pszKeyName,-1)) && (CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam2, -1,NAME_END_A,-1)) ) { bDone = TRUE; pReturn = (PPARAM_LIST)pCurrent->pNext; continue; } // // If 2nd parameter is "BEGIN", create subkey and call this function recursively. // if(CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam2, -1,NAME_BEGIN_A,-1)){ HKEY hkSubKey; LONG lError; lError = RegCreateKeyA(hkDeviceData, pCurrent->pParam1, &hkSubKey); if(ERROR_SUCCESS != lError){ // // Unable to create subkey. // DebugTrace(TRACE_ERROR,(("MigrateDeviceData: ERROR!! Unable to create subkey..\r\n"))); pReturn = NULL; goto MigrateDeviceData_return; } // if(ERROR_SUCCESS != lError) pCurrent = MigrateDeviceData(hkSubKey, (PPARAM_LIST)pCurrent->pNext, pCurrent->pParam1); RegCloseKey(hkSubKey); continue; } // if(0 == lstrcmpiA(pCurrent->pParam2, NAME_BEGIN_A)) // // This is a set of value and data. // lstrcpyA(pCopyBuffer, pCurrent->pParam2); pOrginalBuffer = pCopyBuffer; // // Get key type. // pOrginalBuffer[8] = '\0'; dwType = DecodeHexA(pOrginalBuffer); // // Get data. // Idx = 0; pOrginalBuffer+=9; while('\0' != *pOrginalBuffer){ if('\0' != pOrginalBuffer[2]){ pOrginalBuffer[2] = '\0'; pDataBuffer[Idx++] = (CHAR)DecodeHexA(pOrginalBuffer); pOrginalBuffer+=3; } else { pDataBuffer[Idx++] = (CHAR)DecodeHexA(pOrginalBuffer); break; } } // while('\0' != pCurrent->pParam2[Idx]) // // Create this value. // RegSetValueExA(hkDeviceData, pCurrent->pParam1, 0, dwType, (PBYTE)pDataBuffer, Idx); // // Process next line. // pCurrent = (PPARAM_LIST)pCurrent->pNext; } // while(!bDone) MigrateDeviceData_return: return pReturn; } // MigrateDeviceData() DWORD DecodeHexA( LPSTR lpstr ) { DWORD dwReturn; // // Initialize local. // dwReturn = 0; if(NULL == lpstr){ dwReturn = 0; goto DecodeHexA_return; } // if(NULL == lpstr) // // Skip spaces. // for (LPSTR lpstrThis = lpstr; *lpstrThis && *lpstrThis == TEXT(' '); lpstrThis++) ; while (*lpstrThis) { switch (*lpstrThis) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': dwReturn <<= 4; dwReturn += ((*lpstrThis) - '0'); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': dwReturn <<= 4; dwReturn += 10 + (*lpstrThis - 'a'); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': dwReturn <<= 4; dwReturn += 10 + (*lpstrThis - 'A'); break; default: return dwReturn; } lpstrThis++; } // while (*lpstrThis) DecodeHexA_return: return dwReturn; } // DWORD CString::DecodeHex() BOOL IsNameAlreadyStored( LPTSTR szName ) { BOOL bRet; HKEY hkNameStore; DebugTrace(TRACE_PROC_ENTER,(("IsNameAlreadyStored: Enter... \r\n"))); // // Initialize local. // bRet = FALSE; hkNameStore = (HKEY)INVALID_HANDLE_VALUE; // // Open name store regkey. // if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){ HKEY hkTemp; hkTemp = (HKEY)INVALID_HANDLE_VALUE; // // See if specified name exists in name store. // if(ERROR_SUCCESS == RegOpenKey(hkNameStore, szName, &hkTemp)){ // // Specified name already exists in name store. // bRet = TRUE; RegCloseKey(hkTemp); } // if(ERROR_SUCCESS == RegOpenKey(hkNameStore, szName, &hkTemp)) RegCloseKey(hkNameStore); } // if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)) // IsNameAlreadyStored_return: DebugTrace(TRACE_PROC_LEAVE,(("IsNameAlreadyStored: Leaving... Ret=0x%x\n"), bRet)); return bRet; } // IsFriendlyNameUnique() #if DEAD_CODE #ifdef USE_STIMON // // For the time being always load and start the monitor // HKEY hkRun; if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) { CString csCmdLine; csCmdLine.MakeSystemPath(MONITOR_NAME); csCmdLine.Store (hkRun, REGSTR_VAL_MONITOR); Report(( TEXT("Monitor Command Line %ws\r\n"), (LPCTSTR)csCmdLine)); // Launch it... WinExec(csCmdLine, SW_SHOWNOACTIVATE); RegCloseKey(hkRun); } #endif #endif