Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3833 lines
109 KiB

/******************************************************************************
*
* (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 <stisvc.h>
#include <devguid.h>
#include <regstr.h>
#include <icm.h>
#include <ks.h>
//
// 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