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

  1. /******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: Device.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: KeisukeT
  10. *
  11. * DATE: 27 Mar, 2000
  12. *
  13. * DESCRIPTION:
  14. * Device class for WIA class installer.
  15. *
  16. *
  17. *******************************************************************************/
  18. //
  19. // Precompiled header
  20. //
  21. #include "precomp.h"
  22. #pragma hdrstop
  23. #define INITGUID
  24. #include "device.h"
  25. #include "sti.h"
  26. #include "stiregi.h"
  27. #include <stisvc.h>
  28. #include <devguid.h>
  29. #include <regstr.h>
  30. #include <icm.h>
  31. #include <ks.h>
  32. //
  33. // Parsinc character used to separate field type from value in registry data section
  34. //
  35. #define FIELD_DELIMETER TEXT(',')
  36. BOOL
  37. CDevice::CollectNames(
  38. VOID
  39. )
  40. {
  41. BOOL bRet;
  42. HANDLE hDevInfo;
  43. GUID Guid;
  44. DWORD dwRequired;
  45. DWORD Idx;
  46. SP_DEVINFO_DATA spDevInfoData;
  47. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  48. TCHAR szTempBuffer[MAX_DESCRIPTION];
  49. HKEY hKeyInterface;
  50. HKEY hKeyDevice;
  51. DebugTrace(TRACE_PROC_ENTER,(("CDevice::CollectNames: Enter...\r\n")));
  52. //
  53. // Initialize local.
  54. //
  55. bRet = FALSE;
  56. hDevInfo = INVALID_HANDLE_VALUE;
  57. Guid = GUID_DEVCLASS_IMAGE;
  58. dwRequired = 0;
  59. Idx = 0;
  60. hKeyInterface = (HKEY)INVALID_HANDLE_VALUE;
  61. hKeyDevice = (HKEY)INVALID_HANDLE_VALUE;
  62. memset(szTempBuffer, 0, sizeof(szTempBuffer));
  63. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  64. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  65. //
  66. // Reset device name/ID array.
  67. //
  68. m_csaAllNames.Cleanup();
  69. m_csaAllId.Cleanup();
  70. //
  71. // Get all of installed WIA "devnode" device info set.
  72. //
  73. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE);
  74. if (hDevInfo == INVALID_HANDLE_VALUE) {
  75. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! SetupDiGetClassDevs (devnodes) fails. Err=0x%x\n"), GetLastError()));
  76. bRet = FALSE;
  77. goto CollectNames_return;
  78. }
  79. //
  80. // Enum WIA devnode device friendly name and add them to array.
  81. //
  82. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Looking for DevNodes.\r\n")));
  83. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  84. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  85. //
  86. // Open device registry key.
  87. //
  88. hKeyDevice = SetupDiOpenDevRegKey(hDevInfo,
  89. &spDevInfoData,
  90. DICS_FLAG_GLOBAL,
  91. 0,
  92. DIREG_DRV,
  93. KEY_READ);
  94. if (INVALID_HANDLE_VALUE != hKeyDevice) {
  95. //
  96. // Get FriendlyName.
  97. //
  98. dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0')));
  99. if (RegQueryValueEx(hKeyDevice,
  100. REGSTR_VAL_FRIENDLY_NAME,
  101. NULL,
  102. NULL,
  103. (LPBYTE)szTempBuffer,
  104. &dwRequired) == ERROR_SUCCESS)
  105. {
  106. //
  107. // FriendlyName is found in this device regisgry. Add to the list if valid.
  108. //
  109. if(0 != lstrlen(szTempBuffer)) {
  110. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device name.\r\n"), szTempBuffer));
  111. m_csaAllNames.Add((LPCTSTR)szTempBuffer);
  112. } else { // if(0 != lstrlen(szTempBuffer))
  113. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid FriendleName (length=0).\r\n")));
  114. } // if(0 != lstrlen(szTempBuffer))
  115. } else { // if (RegQueryValueEx()
  116. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get FriendlyName. Err=0x%x\r\n"), GetLastError()));
  117. } // if (RegQueryValueEx()
  118. //
  119. // Get DeviceID.
  120. //
  121. dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0')));
  122. if (RegQueryValueEx(hKeyDevice,
  123. REGSTR_VAL_DEVICE_ID,
  124. NULL,
  125. NULL,
  126. (LPBYTE)szTempBuffer,
  127. &dwRequired) == ERROR_SUCCESS)
  128. {
  129. //
  130. // DeviceID is found in this device regisgry. Add to the list if valid.
  131. //
  132. if(0 != lstrlen(szTempBuffer)) {
  133. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device ID.\r\n"), szTempBuffer));
  134. m_csaAllId.Add((LPCTSTR)szTempBuffer);
  135. } else { // if(0 != lstrlen(szTempBuffer))
  136. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid DeviceID (length=0).\r\n")));
  137. } // if(0 != lstrlen(szTempBuffer))
  138. } else { // if (RegQueryValueEx()
  139. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get DeviceID. Err=0x%x\r\n"), GetLastError()));
  140. } // if (RegQueryValueEx()
  141. //
  142. // Close regkey and continue.
  143. //
  144. RegCloseKey(hKeyDevice);
  145. hKeyInterface = (HKEY)INVALID_HANDLE_VALUE;
  146. szTempBuffer[0] = TEXT('\0');
  147. } else { // if (hKeyDevice != INVALID_HANDLE_VALUE)
  148. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Unable to open Device(%d) RegKey. Err=0x%x\r\n"), Idx, GetLastError()));
  149. } // if (hKeyDevice != INVALID_HANDLE_VALUE)
  150. } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  151. //
  152. // Free "devnode" device info set.
  153. //
  154. SetupDiDestroyDeviceInfoList(hDevInfo);
  155. hDevInfo = INVALID_HANDLE_VALUE;
  156. //
  157. // Enum WIA interface-only device friendly name and add them to array.
  158. //
  159. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Looking for Interfaces.\r\n")));
  160. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PROFILE);
  161. if (hDevInfo == INVALID_HANDLE_VALUE) {
  162. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! SetupDiGetClassDevs (inferfase) fails. Err=0x%x\n"), GetLastError()));
  163. bRet = FALSE;
  164. goto CollectNames_return;
  165. }
  166. spDevInterfaceData.cbSize = sizeof (spDevInterfaceData);
  167. for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) {
  168. hKeyInterface = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  169. &spDevInterfaceData,
  170. 0,
  171. KEY_READ);
  172. if (hKeyInterface != INVALID_HANDLE_VALUE) {
  173. //
  174. // Get FriendlyName.
  175. //
  176. dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0')));
  177. if (RegQueryValueEx(hKeyInterface,
  178. REGSTR_VAL_FRIENDLY_NAME,
  179. NULL,
  180. NULL,
  181. (LPBYTE)szTempBuffer,
  182. &dwRequired) == ERROR_SUCCESS)
  183. {
  184. //
  185. // FriendlyName is found in this interface. Add to the list if valid.
  186. //
  187. if(0 != lstrlen(szTempBuffer)) {
  188. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device name (interface).\r\n"), szTempBuffer));
  189. m_csaAllNames.Add((LPCTSTR)szTempBuffer);
  190. } else { // if(0 != lstrlen(szTempBuffer))
  191. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid FriendleName (length=0).\r\n")));
  192. } // if(0 != lstrlen(szTempBuffer))
  193. } else { // if (RegQueryValueEx()
  194. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get FriendlyName. Err=0x%x\r\n"), GetLastError()));
  195. } // if (RegQueryValueEx()
  196. //
  197. // Get DeviceID.
  198. //
  199. dwRequired = (sizeof(szTempBuffer)-sizeof(TEXT('\0')));
  200. if (RegQueryValueEx(hKeyInterface,
  201. REGSTR_VAL_DEVICE_ID,
  202. NULL,
  203. NULL,
  204. (LPBYTE)szTempBuffer,
  205. &dwRequired) == ERROR_SUCCESS)
  206. {
  207. //
  208. // DeviceID is found in this interface. Add to the list if valid.
  209. //
  210. if(0 != lstrlen(szTempBuffer)) {
  211. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Found %ws as installed device ID (interface).\r\n"), szTempBuffer));
  212. m_csaAllId.Add((LPCTSTR)szTempBuffer);
  213. } else { // if(0 != lstrlen(szTempBuffer))
  214. DebugTrace(TRACE_ERROR,(("CDevice::CollectNames: ERROR!! Invalid DeviceID (length=0).\r\n")));
  215. } // if(0 != lstrlen(szTempBuffer))
  216. } else { // if (RegQueryValueEx()
  217. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: can't get DeviceID. Err=0x%x\r\n"), GetLastError()));
  218. } // if (RegQueryValueEx()
  219. //
  220. // Close registry key and continue.
  221. //
  222. RegCloseKey(hKeyInterface);
  223. hKeyInterface = (HKEY)INVALID_HANDLE_VALUE;
  224. szTempBuffer[0] = TEXT('\0');
  225. } else { // if (hKeyInterface != INVALID_HANDLE_VALUE)
  226. DebugTrace(TRACE_STATUS,(("CDevice::CollectNames: Unable to open Interface(%d) RegKey. Err=0x%x\r\n"), Idx, GetLastError()));
  227. } // if (hKeyInterface != INVALID_HANDLE_VALUE)
  228. } // for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++)
  229. //
  230. // Operation succeeded.
  231. //
  232. bRet = TRUE;
  233. CollectNames_return:
  234. //
  235. // Clean up.
  236. //
  237. if(INVALID_HANDLE_VALUE != hDevInfo){
  238. SetupDiDestroyDeviceInfoList(hDevInfo);
  239. }
  240. if(INVALID_HANDLE_VALUE != hKeyInterface){
  241. RegCloseKey(hKeyInterface);
  242. }
  243. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::CollectNames: Leaving... Ret=0x%x\n"), bRet));
  244. return bRet;
  245. } // CDevice::CollectNames()
  246. // For a device w/ devnode.
  247. CDevice::CDevice(
  248. HDEVINFO hDevInfo,
  249. PSP_DEVINFO_DATA pspDevInfoData,
  250. BOOL bIsPnP
  251. )
  252. {
  253. HKEY hkDevice;
  254. //
  255. // Initizlize local.
  256. //
  257. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  258. //
  259. // Initialize member.
  260. //
  261. m_hMutex = (HANDLE)NULL;
  262. m_hDevInfo = hDevInfo;
  263. m_pspDevInfoData = pspDevInfoData;
  264. m_bIsPnP = bIsPnP;
  265. m_bDefaultDevice = FALSE;
  266. m_bVideoDevice = FALSE;
  267. m_bInfProceeded = FALSE;
  268. m_bInterfaceOnly = FALSE;
  269. m_bIsMigration = FALSE;
  270. m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE;
  271. m_dwCapabilities = 0;
  272. m_dwInterfaceIndex = INVALID_DEVICE_INDEX;
  273. m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL;
  274. m_pExtraDeviceData = NULL;
  275. m_csFriendlyName.Empty();
  276. m_csInf.Empty();
  277. m_csInstallSection.Empty();
  278. m_csDriverDescription.Empty();
  279. m_csPort.Empty();
  280. m_csDeviceID.Empty();
  281. //
  282. // In case of upgrade, use original FriendlyName.
  283. //
  284. hkDevice = SetupDiOpenDevRegKey(m_hDevInfo,
  285. m_pspDevInfoData,
  286. DICS_FLAG_GLOBAL,
  287. 0,
  288. DIREG_DRV,
  289. KEY_READ);
  290. if(INVALID_HANDLE_VALUE != hkDevice){
  291. //
  292. // Device registry found. Read its FriendlyName.
  293. //
  294. m_csDriverDescription.Load(hkDevice, FRIENDLYNAME);
  295. m_csDeviceID.Load(hkDevice, REGSTR_VAL_DEVICE_ID);
  296. m_csFriendlyName.Load(hkDevice, FRIENDLYNAME);
  297. RegCloseKey(hkDevice);
  298. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  299. } // if(INVALID_HANDLE_VALUE != hkDevice)
  300. //
  301. // Get the number of installed devices.
  302. //
  303. GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice);
  304. } // CDevice::CDevice()
  305. // For a interface-only device.
  306. CDevice::CDevice(
  307. HDEVINFO hDevInfo,
  308. DWORD dwDeviceIndex
  309. )
  310. {
  311. //
  312. // Initialize member.
  313. //
  314. m_hMutex = (HANDLE)NULL;
  315. m_hDevInfo = hDevInfo;
  316. m_pspDevInfoData = NULL;
  317. m_bIsPnP = FALSE;
  318. m_bDefaultDevice = FALSE;
  319. m_bVideoDevice = FALSE;
  320. m_bInfProceeded = FALSE;
  321. m_bInterfaceOnly = TRUE;
  322. m_bIsMigration = FALSE;
  323. m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE;
  324. m_dwCapabilities = 0;
  325. m_dwInterfaceIndex = dwDeviceIndex;
  326. m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL;
  327. m_pExtraDeviceData = NULL;
  328. m_csFriendlyName.Empty();
  329. m_csInf.Empty();
  330. m_csInstallSection.Empty();
  331. m_csDriverDescription.Empty();
  332. m_csPort.Empty();
  333. m_csDeviceID.Empty();
  334. //
  335. // Get the number of installed devices.
  336. //
  337. GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice);
  338. } // CDevice::CDevice()
  339. // For a interface-only device.
  340. CDevice::CDevice(
  341. PDEVICE_INFO pMigratingDevice
  342. )
  343. {
  344. TCHAR StringBuffer[MAX_PATH+1];
  345. TCHAR WindowsDir[MAX_PATH+1];
  346. //
  347. // Initialize local.
  348. //
  349. memset(StringBuffer, 0, sizeof(StringBuffer));
  350. memset(WindowsDir, 0, sizeof(WindowsDir));
  351. //
  352. // Initialize member.
  353. //
  354. m_hMutex = (HANDLE)NULL;
  355. m_hDevInfo = NULL;
  356. m_pspDevInfoData = NULL;
  357. m_bIsPnP = FALSE;
  358. m_bDefaultDevice = FALSE;
  359. m_bVideoDevice = FALSE;
  360. m_bInfProceeded = FALSE;
  361. m_bInterfaceOnly = TRUE;
  362. m_bIsMigration = TRUE;
  363. m_hkInterfaceRegistry = (HKEY)INVALID_HANDLE_VALUE;
  364. m_dwCapabilities = 0;
  365. m_dwInterfaceIndex = INVALID_DEVICE_INDEX;
  366. m_pfnDevnodeSelCallback = (DEVNODESELCALLBACK) NULL;
  367. //
  368. // Copy migration data.
  369. //
  370. AtoT(StringBuffer, pMigratingDevice->pszInfPath);
  371. m_csInf = StringBuffer;
  372. if(0 != GetWindowsDirectory(WindowsDir, MAX_PATH)){
  373. _sntprintf(StringBuffer, ARRAYSIZE(StringBuffer)-1, TEXT("%ws\\inf\\%ws"), WindowsDir, (LPTSTR)m_csInf);
  374. m_csInf = StringBuffer;
  375. } // if(0 != GetWindowsDirectory(WindowsDir, MAX_PATH))
  376. AtoT(StringBuffer, pMigratingDevice->pszInfSection);
  377. m_csInstallSection = StringBuffer;
  378. AtoT(StringBuffer, pMigratingDevice->pszFriendlyName);
  379. m_csDriverDescription = StringBuffer;
  380. AtoT(StringBuffer, pMigratingDevice->pszFriendlyName);
  381. m_csFriendlyName = StringBuffer;
  382. AtoT(StringBuffer, pMigratingDevice->pszCreateFileName);
  383. m_csPort = StringBuffer;
  384. m_pExtraDeviceData = pMigratingDevice->pDeviceDataParam;
  385. m_csDeviceID.Empty();
  386. //
  387. // Get the number of installed devices.
  388. //
  389. GetDeviceCount(&m_dwNumberOfWiaDevice, &m_dwNumberOfStiDevice);
  390. } // CDevice::CDevice()
  391. CDevice::~CDevice(
  392. )
  393. {
  394. HKEY hkNameStore;
  395. if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){
  396. //
  397. // Delete FriendlyName and DeviceId in name store.
  398. //
  399. RegDeleteKey(hkNameStore, m_csFriendlyName);
  400. RegDeleteKey(hkNameStore, m_csDeviceID);
  401. RegCloseKey(hkNameStore);
  402. } // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore))
  403. //
  404. // Make sure Mutex is released.
  405. //
  406. ReleaseInstallerMutex();
  407. } // CDevice::~CDevice()
  408. BOOL
  409. CDevice::IsSameDevice(
  410. HDEVINFO hDevInfo,
  411. PSP_DEVINFO_DATA pspDevInfoSet
  412. )
  413. {
  414. BOOL bRet;
  415. SP_DRVINFO_DATA spDrvInfoData;
  416. DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsSameDevice: Enter...\r\n")));
  417. //
  418. // Initialize local.
  419. //
  420. bRet = FALSE;
  421. memset(&spDrvInfoData, 0, sizeof(spDrvInfoData));
  422. //
  423. // Get default FriendlyName. It's used to check if it's same device or not.
  424. //
  425. spDrvInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
  426. if (!SetupDiGetSelectedDriver (hDevInfo, pspDevInfoSet, &spDrvInfoData)){
  427. bRet = FALSE;
  428. goto IsSameDevice_return;
  429. } // if (SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDevInfoData))
  430. //
  431. // See if it has same description of current device. (TRUE=same)
  432. //
  433. bRet = (0 == lstrcmp((LPCTSTR)spDrvInfoData.Description, (LPCTSTR)m_csPdoDescription));
  434. IsSameDevice_return:
  435. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsSameDevice: Leaving... Ret=0x%x\n"), bRet));
  436. return bRet;
  437. } // CDevice::IsSameDevice()
  438. BOOL
  439. CDevice::IsFriendlyNameUnique(
  440. LPTSTR szFriendlyName
  441. )
  442. //
  443. // Note:
  444. // Before calling this function, caller has to make sure mutex is acquired.
  445. //
  446. {
  447. BOOL bRet;
  448. DWORD Idx;
  449. DWORD dwNumberOfName;
  450. DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsFriendlyNameUnique: Enter... \r\n")));
  451. //
  452. // Initialize local.
  453. //
  454. bRet = FALSE;
  455. Idx = 0;
  456. dwNumberOfName = m_csaAllNames.Count();
  457. //
  458. // If given name is same as generated one, it's unique.
  459. //
  460. if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName))){
  461. bRet = TRUE;
  462. goto IsFriendlyNameUnique_return;
  463. } // if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName)))
  464. //
  465. // Check any existing name matches given name.
  466. //
  467. for (Idx = 0; Idx < dwNumberOfName; Idx++) {
  468. DebugTrace(TRACE_STATUS,(("CDevice::IsFriendlyNameUnique: Name compare %ws and %ws.\r\n"),m_csaAllNames[Idx], szFriendlyName));
  469. if (0 == lstrcmpi(m_csaAllNames[Idx], szFriendlyName)){
  470. bRet = FALSE;
  471. goto IsFriendlyNameUnique_return;
  472. }
  473. } // for (Idx = 0; Idx < dwNumberOfName; Idx)
  474. //
  475. // Look in name store.
  476. //
  477. if(IsNameAlreadyStored(szFriendlyName)){
  478. bRet = FALSE;
  479. goto IsFriendlyNameUnique_return;
  480. } // if(IsNameAlreadyStored(szFriendlyName))
  481. //
  482. // This device name is unique.
  483. //
  484. bRet = TRUE;
  485. IsFriendlyNameUnique_return:
  486. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsFriendlyNameUnique: Leaving... Ret=0x%x\n"), bRet));
  487. return bRet;
  488. } // CDevice::IsFriendlyNameUnique()
  489. BOOL
  490. CDevice::IsDeviceIdUnique(
  491. LPTSTR szDeviceId
  492. )
  493. {
  494. BOOL bRet;
  495. DWORD Idx;
  496. DWORD dwNumberOfId;
  497. DebugTrace(TRACE_PROC_ENTER,(("CDevice::IsDeviceIdUnique: Enter... \r\n")));
  498. //
  499. // Initialize local.
  500. //
  501. bRet = FALSE;
  502. Idx = 0;
  503. dwNumberOfId = m_csaAllId.Count();
  504. //
  505. // If given ID is same as generated one, it's unique.
  506. //
  507. if(0 == lstrcmp(szDeviceId, (LPTSTR)(m_csDeviceID))){
  508. bRet = TRUE;
  509. goto IsDeviceIdUnique_return;
  510. } // if(0 == lstrcmp(szFriendlyName, (LPTSTR)(m_csFriendlyName)))
  511. //
  512. // Check any existing name matches given name.
  513. //
  514. for (Idx = 0; Idx < dwNumberOfId; Idx++) {
  515. DebugTrace(TRACE_STATUS,(("CDevice::IsDeviceIdUnique: DeviceId compare %ws and %ws.\r\n"),m_csaAllId[Idx], szDeviceId));
  516. if (0 == lstrcmpi(m_csaAllId[Idx], szDeviceId)){
  517. bRet = FALSE;
  518. goto IsDeviceIdUnique_return;
  519. } // if (0 == lstrcmpi(m_csaAllId[Idx], szFriendlyName))
  520. } // for (Idx = 0; Idx < dwNumberOfName; Idx)
  521. //
  522. // Look in name store.
  523. //
  524. if(IsNameAlreadyStored(szDeviceId)){
  525. bRet = FALSE;
  526. goto IsDeviceIdUnique_return;
  527. } // if(IsNameAlreadyStored(szFriendlyName))
  528. //
  529. // This device name is unique.
  530. //
  531. bRet = TRUE;
  532. IsDeviceIdUnique_return:
  533. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::IsDeviceIdUnique: Leaving... Ret=0x%x\n"), bRet));
  534. return bRet;
  535. } // CDevice::IsDeviceIdUnique()
  536. BOOL
  537. CDevice::NameDefaultUniqueName(
  538. VOID
  539. )
  540. {
  541. SP_DRVINFO_DATA spDrvInfoData;
  542. TCHAR szFriendly[MAX_DESCRIPTION];
  543. TCHAR szDescription[MAX_DESCRIPTION];
  544. UINT i;
  545. BOOL bRet;
  546. HKEY hkNameStore;
  547. DWORD dwError;
  548. DebugTrace(TRACE_PROC_ENTER,(("CDevice::NameDefaultUniqueName: Enter... \r\n")));
  549. //
  550. // Initialize local.
  551. //
  552. bRet = FALSE;
  553. hkNameStore = (HKEY)INVALID_HANDLE_VALUE;
  554. memset(szFriendly, 0, sizeof(szFriendly));
  555. memset(szDescription, 0, sizeof(szDescription));
  556. memset(&spDrvInfoData, 0, sizeof(spDrvInfoData));
  557. //
  558. // Acquire mutex to make sure not duplicating FriendlyName/DeviceId.
  559. //
  560. dwError = AcquireInstallerMutex(MAX_MUTEXTIMEOUT);
  561. if(ERROR_SUCCESS != dwError){ // it must be done at least in 60 sec.
  562. if(WAIT_ABANDONED == dwError){
  563. DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Mutex abandoned. Continue...\r\n"));
  564. } else if(WAIT_TIMEOUT == dwError){
  565. DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to acquire mutex in 60 sec. Bail out.\r\n"));
  566. bRet = FALSE;
  567. goto NameDefaultUniqueName_return;
  568. } // else if(WAIT_TIMEOUT == dwError)
  569. } // if(ERROR_SUCCESS != AcquireInstallerMutex(60000))
  570. //
  571. // Get all installed WIA device friendly name.
  572. //
  573. CollectNames();
  574. //
  575. // Generate unique device ID.
  576. //
  577. if(m_csDeviceID.IsEmpty()){
  578. GenerateUniqueDeviceId();
  579. } // if(m_csDeviceID.IsEmpty())
  580. if(m_csFriendlyName.IsEmpty()){
  581. //
  582. // Get default FriendlyName. It's used to check if it's same device or not.
  583. //
  584. spDrvInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
  585. if (!SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDrvInfoData)){
  586. bRet = FALSE;
  587. goto NameDefaultUniqueName_return;
  588. } // if (SetupDiGetSelectedDriver (m_hDevInfo, m_pspDevInfoData, &spDevInfoData))
  589. //
  590. // Copy default Device description. (= default FriendlyName)
  591. // Also set Vnedor name.
  592. //
  593. m_csVendor = (LPCTSTR)spDrvInfoData.MfgName;
  594. m_csPdoDescription = (LPCTSTR)spDrvInfoData.Description;
  595. //
  596. // Find unique name for this device.
  597. //
  598. if(m_csDriverDescription.IsEmpty()){
  599. lstrcpyn(szDescription, m_csPdoDescription, ARRAYSIZE(szDescription)-1);
  600. m_csDriverDescription = szDescription;
  601. } else {
  602. lstrcpyn(szDescription, m_csDriverDescription, ARRAYSIZE(szDescription)-1);
  603. }
  604. lstrcpyn(szFriendly, szDescription, ARRAYSIZE(szFriendly)-1);
  605. for (i = 2; !IsFriendlyNameUnique(szFriendly); i++) {
  606. _sntprintf(szFriendly, ARRAYSIZE(szFriendly)-1, TEXT("%ws #%d"), szDescription, i);
  607. }
  608. //
  609. // Set created FriendlyName.
  610. //
  611. m_csFriendlyName = szFriendly;
  612. } // if(m_csFriendlyName.IsEmpty())
  613. //
  614. // Save FriendlyName and DeviceId in registry. It'll be deleted when installation is completed.
  615. //
  616. if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){
  617. HKEY hkTemp;
  618. hkTemp = (HKEY)INVALID_HANDLE_VALUE;
  619. //
  620. // Create FriendlyName key.
  621. //
  622. if(ERROR_SUCCESS == RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp)){
  623. RegCloseKey(hkTemp);
  624. hkTemp = (HKEY)INVALID_HANDLE_VALUE;
  625. } else {
  626. DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create %s key.\r\n", (LPTSTR)m_csFriendlyName));
  627. } // if(ERROR_SUCCESS != RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp))
  628. //
  629. // Create DeviceId key.
  630. //
  631. if(ERROR_SUCCESS == RegCreateKey(hkNameStore, (LPTSTR)m_csDeviceID, &hkTemp)){
  632. RegCloseKey(hkTemp);
  633. hkTemp = (HKEY)INVALID_HANDLE_VALUE;
  634. } else {
  635. DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create %s key.\r\n", (LPTSTR)m_csDeviceID));
  636. } // if(ERROR_SUCCESS != RegCreateKey(hkNameStore, (LPTSTR)m_csFriendlyName, &hkTemp))
  637. RegCloseKey(hkNameStore);
  638. } else { // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore))
  639. DebugTrace(TRACE_ERROR,("CDevice::NameDefaultUniqueName: ERROR!! Unable to create NameStore key.\r\n"));
  640. } // else(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore))
  641. //
  642. // Operation succeeded.
  643. //
  644. DebugTrace(TRACE_STATUS,(("CDevice::NameDefaultUniqueName: Device default name=%ws.\r\n"), (LPTSTR)m_csFriendlyName));
  645. bRet = TRUE;
  646. NameDefaultUniqueName_return:
  647. //
  648. // Release mutex. ReleaseInstallerMutex() will handle invalid handle also, so we can call anyway.
  649. //
  650. ReleaseInstallerMutex();
  651. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::NameDefaultUniqueName: Leaving... Ret=0x%x\n"), bRet));
  652. return bRet;
  653. } // CDevice::NameDefaultUniqueName()
  654. BOOL
  655. CDevice::GenerateUniqueDeviceId(
  656. VOID
  657. )
  658. {
  659. DWORD Idx;
  660. BOOL bRet;
  661. TCHAR szDeviceId[MAX_DESCRIPTION];
  662. DebugTrace(TRACE_PROC_ENTER,(("CDevice::GenerateUniqueDeviceId: Enter... \r\n")));
  663. //
  664. // Initialize local.
  665. //
  666. bRet = FALSE;
  667. memset(szDeviceId, 0, sizeof(szDeviceId));
  668. //
  669. // Find unique name for this device.
  670. //
  671. _sntprintf(szDeviceId, ARRAYSIZE(szDeviceId)-1, TEXT("%ws\\%04d"), WIA_GUIDSTRING, 0);
  672. for (Idx = 1; !IsDeviceIdUnique(szDeviceId); Idx++) {
  673. _sntprintf(szDeviceId, ARRAYSIZE(szDeviceId)-1, TEXT("%ws\\%04d"), WIA_GUIDSTRING, Idx);
  674. }
  675. //
  676. // Set created hardwareId.
  677. //
  678. m_csDeviceID = szDeviceId;
  679. //
  680. // Operation succeeded.
  681. //
  682. DebugTrace(TRACE_STATUS,(("CDevice::GenerateUniqueDeviceId: DeviceID=%ws.\r\n"), (LPTSTR)m_csDeviceID));
  683. bRet = TRUE;
  684. // GenerateUniqueDeviceId_return:
  685. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::GenerateUniqueDeviceId: Leaving... Ret=0x%x\n"), bRet));
  686. return bRet;
  687. } // CDevice::GenerateUniqueDeviceId()
  688. BOOL
  689. CDevice::Install(
  690. )
  691. /*++
  692. Routine Description:
  693. Worker function for DIF_INSTALL setup message
  694. Arguments:
  695. none
  696. Return Value:
  697. TRUE - successful
  698. FALSE - non successful
  699. --*/
  700. {
  701. BOOL bRet;
  702. DebugTrace(TRACE_PROC_ENTER,(("CDevice::Install: Enter... \r\n")));
  703. //
  704. // Initialize local.
  705. //
  706. bRet = FALSE;
  707. //
  708. // Class installer only handles file copy.
  709. //
  710. if(IsMigration()){
  711. CreateDeviceInterfaceAndInstall();
  712. } else { // if(IsMigration())
  713. if ( !HandleFilesInstallation()){
  714. DebugTrace(TRACE_ERROR, (("CDevice::Install: HandleFilesInstallation Failed. Err=0x%x"), GetLastError()));
  715. bRet = FALSE;
  716. goto Install_return;
  717. } // if ( !HandleFilesInstallation())
  718. } // else(IsMigration())
  719. //
  720. // We are successfully finished
  721. //
  722. bRet = TRUE;
  723. Install_return:
  724. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::Install: Leaving... Ret=0x%x\n"), bRet));
  725. return bRet;
  726. }
  727. DWORD
  728. CDevice::Remove(
  729. PSP_REMOVEDEVICE_PARAMS lprdp
  730. )
  731. /*++
  732. Routine Description:
  733. Remove
  734. method which is called when device is being removed
  735. Arguments:
  736. Return Value:
  737. Side effects:
  738. --*/
  739. {
  740. CString csUninstallSection;
  741. CString csInf;
  742. CString csSubClass;
  743. DWORD dwCapabilities;
  744. PVOID pvContext;
  745. HKEY hkDrv;
  746. HKEY hkRun;
  747. GUID Guid;
  748. BOOL bIsServiceStopped;
  749. BOOL bIsSti;
  750. BOOL bSetParamRet;
  751. PSP_FILE_CALLBACK SavedCallback;
  752. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  753. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  754. DWORD dwReturn;
  755. LPTSTR pSec;
  756. DebugTrace(TRACE_PROC_ENTER,(("CDevice::Remove: Enter... \r\n")));
  757. //
  758. // Initialize local.
  759. //
  760. pvContext = NULL;
  761. hkDrv = NULL;
  762. hkRun = NULL;
  763. bSetParamRet = FALSE;
  764. SavedCallback = NULL;
  765. dwReturn = NO_ERROR;
  766. Guid = GUID_DEVCLASS_IMAGE;
  767. bIsServiceStopped = FALSE;
  768. bIsSti = FALSE;
  769. memset(&DeviceInstallParams, 0, sizeof(DeviceInstallParams));
  770. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  771. //
  772. // NT setup inconsistently set this bit , disable for now
  773. //
  774. #if SETUP_PROBLEM
  775. if (!(lprdp->Scope & DI_REMOVEDEVICE_GLOBAL)) {
  776. goto Remove_return;
  777. }
  778. #endif
  779. //
  780. // The name of the uninstall section was stored during installation
  781. //
  782. if(IsInterfaceOnlyDevice()){
  783. DebugTrace(TRACE_STATUS,(("CDevice::Remove: This is Interface-only device.\r\n")));
  784. //
  785. // Get interface from index.
  786. //
  787. spDevInterfaceData.cbSize = sizeof(spDevInterfaceData);
  788. if(!SetupDiEnumDeviceInterfaces(m_hDevInfo, NULL, &Guid, m_dwInterfaceIndex, &spDevInterfaceData)){
  789. DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiEnumDeviceInterfaces() failed. Err=0x%x \r\n"), GetLastError()));
  790. dwReturn = ERROR_NO_DEFAULT_DEVICE_INTERFACE;
  791. goto Remove_return;
  792. }
  793. //
  794. // Create interface reg-key.
  795. //
  796. hkDrv = SetupDiOpenDeviceInterfaceRegKey(m_hDevInfo,
  797. &spDevInterfaceData,
  798. 0,
  799. KEY_READ);
  800. } else { // if(IsInterfaceOnlyDevice())
  801. DebugTrace(TRACE_STATUS,(("CDevice::Remove: This is devnode device.\r\n")));
  802. hkDrv = SetupDiOpenDevRegKey(m_hDevInfo,
  803. m_pspDevInfoData,
  804. DICS_FLAG_GLOBAL,
  805. 0,
  806. DIREG_DRV,
  807. KEY_READ);
  808. } // if(IsInterfaceOnlyDevice())
  809. if (hkDrv == INVALID_HANDLE_VALUE) {
  810. DebugTrace(TRACE_ERROR,(("CDevice::Remove: Invalid device/interface regkey handle. Err=0x%x \r\n"), GetLastError()));
  811. dwReturn = ERROR_KEY_DOES_NOT_EXIST;
  812. goto Remove_return;
  813. }
  814. //
  815. // Retrieve the name of the .INF File
  816. //
  817. csUninstallSection.Load (hkDrv, UNINSTALLSECTION);
  818. csInf.Load (hkDrv, INFPATH);
  819. csSubClass.Load(hkDrv, SUBCLASS);
  820. GetDwordFromRegistry(hkDrv, CAPABILITIES, &dwCapabilities);
  821. //
  822. // See if we need STI/WIA specific operation.
  823. //
  824. if( (!csSubClass.IsEmpty())
  825. && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) )
  826. {
  827. //
  828. // This is STI/WIA device.
  829. //
  830. bIsSti = TRUE;
  831. //
  832. // Delete "Scanner and Camera Wizard" menu.
  833. //
  834. if( (dwCapabilities & STI_GENCAP_WIA)
  835. && (m_dwNumberOfWiaDevice <= 1) )
  836. {
  837. DeleteWiaShortcut();
  838. //
  839. // remove following key for performance improvement.
  840. //
  841. if(ERROR_SUCCESS != RegDeleteKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT)){
  842. DebugTrace(TRACE_ERROR,(("CDevice::Remove: RegDeleteKey() failed. Err=0x%x. \r\n"), GetLastError()));
  843. } // if(ERROR_SUCCESS != RegDeleteKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT))
  844. } // if( (dwCapabilities & STI_GENCAP_WIA)
  845. //
  846. // If this is the last STI/WIA device, set WIA service as Manual.
  847. //
  848. if(m_dwNumberOfStiDevice <= 1){
  849. HKEY hkeyTemp;
  850. DebugTrace(TRACE_STATUS,(("CDevice::Remove: Last WIA device being removed. Set WIA service as MANUAL.\r\n")));
  851. //
  852. // No more still image devices -- change service to Manual start
  853. //
  854. // StopWiaService();
  855. SetServiceStart(STI_SERVICE_NAME, SERVICE_DEMAND_START);
  856. bIsServiceStopped = TRUE;
  857. //
  858. //
  859. // Also remove shell's flag about WIA device presence, this should be portable
  860. // to NT
  861. //
  862. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun) == 0) {
  863. RegDeleteValue (hkRun, REGSTR_VAL_WIA_PRESENT);
  864. RegCloseKey(hkRun);
  865. hkRun = NULL;
  866. } // if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun) == 0)
  867. } // if(m_dwNumberOfStiDevice <= 1)
  868. } // if (m_dwNumberOfDevice <= 1)
  869. //
  870. // Operaion succeeded.
  871. //
  872. dwReturn = NO_ERROR;
  873. Remove_return:
  874. if(IsInterfaceOnlyDevice()){
  875. //
  876. // Delete interface resigtry key.
  877. //
  878. if(!SetupDiDeleteDeviceInterfaceRegKey(m_hDevInfo, &spDevInterfaceData, 0)){
  879. DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiDeleteDeviceInterfaceRegKey failed. Err=0x%x \r\n"), GetLastError()));
  880. } // if(!SetupDiDeleteDeviceInterfaceRegKey(m_hDevInfo, &spDevInterfaceData, 0))
  881. //
  882. // Remove the interface.
  883. //
  884. if(!SetupDiRemoveDeviceInterface(m_hDevInfo, &spDevInterfaceData)){
  885. DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiRemoveDeviceInterface failed. Err=0x%x \r\n"), GetLastError()));
  886. } // if(!SetupDiRemoveDeviceInterface(m_hDevInfo, &spDevInterfaceData))
  887. } else { // if(IsInterfaceOnlyDevice())
  888. //
  889. // Delete device resigtry key.
  890. //
  891. SetupDiDeleteDevRegKey (m_hDevInfo, m_pspDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_BOTH);
  892. if(NO_ERROR == dwReturn){
  893. //
  894. // Remove the device node anyway.
  895. //
  896. if(!SetupDiRemoveDevice(m_hDevInfo, m_pspDevInfoData)){
  897. DebugTrace(TRACE_ERROR,(("CDevice::Remove: SetupDiRemoveDevice failed. Err=0x%x \r\n"), GetLastError()));
  898. //
  899. // Failed to remove device instance from system. Let default installer do that.
  900. //
  901. dwReturn = ERROR_DI_DO_DEFAULT;
  902. } // if(!SetupDiRemoveDevice(m_hDevInfo, m_pspDevInfoData))
  903. } // if(ERROR_DI_DO_DEFAULT != dwReturn)
  904. } // else (IsInterfaceOnlyDevice())
  905. //
  906. // Notify WIA service device removal
  907. //
  908. if(bIsSti){
  909. WiaDeviceEnum();
  910. } // if(TRUE == bIsSti)
  911. //
  912. // Clean up.
  913. //
  914. if(IS_VALID_HANDLE(hkDrv)){
  915. RegCloseKey (hkDrv);
  916. hkDrv = NULL;
  917. }
  918. if(IS_VALID_HANDLE(hkRun)){
  919. RegCloseKey (hkRun);
  920. hkRun = NULL;
  921. }
  922. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::Remove: Leaving... Ret=0x%x\n"), dwReturn));
  923. return dwReturn;
  924. }
  925. BOOL
  926. CDevice::PreprocessInf(
  927. VOID
  928. )
  929. {
  930. BOOL bRet;
  931. HINF hInf;
  932. CString csCapabilities;
  933. CString csDeviceType;
  934. CString csDeviceSubType;
  935. CString csDriverDescription;
  936. DebugTrace(TRACE_PROC_ENTER,(("CDevice::PreprocessInf: Enter... \r\n")));
  937. //
  938. // Initialize local.
  939. //
  940. bRet = FALSE;
  941. hInf = INVALID_HANDLE_VALUE;
  942. //
  943. // Check if INF has already been proceeded.
  944. //
  945. if(m_bInfProceeded){
  946. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: INF is already processed. \r\n")));
  947. bRet = TRUE;
  948. goto ProcessInf_return;
  949. }
  950. //
  951. // Get Inf file/section name.
  952. //
  953. if( m_csInf.IsEmpty() || m_csInstallSection.IsEmpty()){
  954. GetInfInforamtion();
  955. } // if( m_csInf.IsEmpty() || m_csInstallSection.IsEmpty())
  956. //
  957. // Open INF file.
  958. //
  959. hInf = SetupOpenInfFile(m_csInf,
  960. NULL,
  961. INF_STYLE_WIN4,
  962. NULL);
  963. if(!IS_VALID_HANDLE(hInf)){
  964. DebugTrace(TRACE_ERROR, (("CDevice::PreprocessInf: Unable to open INF(%ws). Error = 0x%x.\r\n"),m_csInf, GetLastError()));
  965. bRet = FALSE;
  966. goto ProcessInf_return;
  967. } // if(!IS_VALID_HANDLE(hInf))
  968. //
  969. // Check if WiaSection entry exists.
  970. //
  971. m_csWiaSection.Load (hInf, m_csInstallSection, WIASECTION);
  972. if(!m_csWiaSection.IsEmpty()){
  973. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: WiaSection exists. Acquire all informaiton from WiaSection..\r\n")));
  974. //
  975. // Install interface from WiaSection for MFP device.
  976. //
  977. m_csInstallSection = m_csWiaSection;
  978. m_bInterfaceOnly = TRUE;
  979. } // if(!m_csWiaSection.IsEmpty())
  980. //
  981. // Get all information required for installation from inf file.
  982. //
  983. m_csSubClass.Load (hInf, m_csInstallSection, SUBCLASS);
  984. m_csUSDClass.Load (hInf, m_csInstallSection, USDCLASS);
  985. m_csEventSection.Load (hInf, m_csInstallSection, EVENTS);
  986. m_csConnection.Load (hInf, m_csInstallSection, CONNECTION);
  987. m_csIcmProfile.Load (hInf, m_csInstallSection, ICMPROFILES);
  988. m_csPropPages.Load (hInf, m_csInstallSection, PROPERTYPAGES);
  989. m_csDataSection.Load (hInf, m_csInstallSection, DEVICESECTION);
  990. m_csUninstallSection.Load (hInf, m_csInstallSection, UNINSTALLSECTION);
  991. m_csPortSelect.Load (hInf, m_csInstallSection, PORTSELECT);
  992. if(!IsMigration()){
  993. csDriverDescription.Load(hInf, m_csInstallSection, DESCRIPTION);
  994. if(!csDriverDescription.IsEmpty()){
  995. m_csDriverDescription = csDriverDescription;
  996. if(TRUE != NameDefaultUniqueName()){
  997. //
  998. // Unable to generate FriendlyName.
  999. //
  1000. bRet = FALSE;
  1001. goto ProcessInf_return;
  1002. } // if(TRUE != NameDefaultUniqueName())
  1003. } // if(!m_csDriverDescription.IsEmpty())
  1004. } // if(!IsMigration())
  1005. csCapabilities.Load (hInf, m_csInstallSection, CAPABILITIES);
  1006. csDeviceType.Load (hInf, m_csInstallSection, DEVICETYPE);
  1007. csDeviceSubType.Load (hInf, m_csInstallSection, DEVICESUBTYPE);
  1008. m_dwCapabilities = csCapabilities.Decode();
  1009. m_dwDeviceType = csDeviceType.Decode();
  1010. m_dwDeviceSubType = csDeviceSubType.Decode();
  1011. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: --------------- INF parameters --------------- \r\n")));
  1012. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Description : %ws\n"), (LPTSTR)m_csDriverDescription));
  1013. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: SubClass : %ws\n"), (LPTSTR)m_csSubClass));
  1014. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: USDClass : %ws\n"), (LPTSTR)m_csUSDClass));
  1015. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: EventSection : %ws\n"), (LPTSTR)m_csEventSection));
  1016. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Connection : %ws\n"), (LPTSTR)m_csConnection));
  1017. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: IcmProfile : %ws\n"), (LPTSTR)m_csIcmProfile));
  1018. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: PropPages : %ws\n"), (LPTSTR)m_csPropPages));
  1019. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DataSection : %ws\n"), (LPTSTR)m_csDataSection));
  1020. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: UninstallSection : %ws\n"), (LPTSTR)m_csUninstallSection));
  1021. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: Capabilities : 0x%x\n"), m_dwCapabilities));
  1022. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DeviceType : 0x%x\n"), m_dwDeviceType));
  1023. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: DeviceSubType : 0x%x\n"), m_dwDeviceSubType));
  1024. //
  1025. // Set video device flag if applicable.
  1026. //
  1027. if(StiDeviceTypeStreamingVideo == m_dwDeviceType){
  1028. DebugTrace(TRACE_STATUS,(("CDevice::PreprocessInf: This is video device.\r\n")));
  1029. m_bVideoDevice = TRUE;
  1030. } else {
  1031. m_bVideoDevice = FALSE;
  1032. }
  1033. //
  1034. // Operation succeeded.
  1035. //
  1036. bRet = TRUE;
  1037. m_bInfProceeded = TRUE;
  1038. ProcessInf_return:
  1039. if(IS_VALID_HANDLE(hInf)){
  1040. SetupCloseInfFile(hInf);
  1041. hInf = INVALID_HANDLE_VALUE;
  1042. } // if(IS_VALID_HANDLE(hInf))
  1043. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PreprocessInf: Leaving... Ret=0x%x \r\n"), bRet));
  1044. return bRet;
  1045. } // CDevice::PreprocessInf()
  1046. BOOL
  1047. CDevice::PreInstall(
  1048. VOID
  1049. )
  1050. {
  1051. BOOL bRet;
  1052. HKEY hkDrv;
  1053. GUID Guid;
  1054. HDEVINFO hDevInfo;
  1055. SP_DEVINFO_DATA spDevInfoData;
  1056. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  1057. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  1058. BOOL bUseDefaultDevInfoSet;
  1059. DWORD dwRequiredSize;
  1060. DebugTrace(TRACE_PROC_ENTER,(("CDevice::PreInstall: Enter... \r\n")));
  1061. //
  1062. // Initialize local.
  1063. //
  1064. bRet = FALSE;
  1065. //
  1066. // Get all INF parameter.
  1067. //
  1068. if(!PreprocessInf()){
  1069. DebugTrace(TRACE_ERROR,(("CDevice::PreInstall: ERROR!! Unable to process INF.\r\n")));
  1070. bRet = FALSE;
  1071. goto PreInstall_return;
  1072. }
  1073. /**************************************
  1074. if(!IsInterfaceOnlyDevice()){
  1075. //
  1076. // Register device if it's getting manually installed and not "interface-only" device..
  1077. //
  1078. if(!IsPnpDevice()){
  1079. if (!SetupDiRegisterDeviceInfo(m_hDevInfo, m_pspDevInfoData, 0, NULL, NULL, NULL)) {
  1080. DebugTrace(TRACE_ERROR,(("CDevice::PreInstall: SetupDiRegisterDeviceInfo failed. Err=0x%x.\r\n"),GetLastError()));
  1081. bRet = FALSE;
  1082. goto PreInstall_return;
  1083. }
  1084. } // if(!IsPnpDevice())
  1085. } // if(IsInterfaceOnlyDevice())
  1086. **************************************/
  1087. //
  1088. // Clean up.
  1089. //
  1090. //
  1091. // Operation succeeded.
  1092. //
  1093. bRet = TRUE;
  1094. PreInstall_return:
  1095. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PreInstall: Leaving... Ret=0x%x.\r\n"), bRet));
  1096. return bRet;
  1097. }
  1098. BOOL
  1099. CDevice::PostInstall(
  1100. BOOL bSucceeded
  1101. )
  1102. {
  1103. BOOL bRet;
  1104. HKEY hkRun;
  1105. HKEY hkDrv;
  1106. DWORD dwFlagPresent;
  1107. CString csInfFilename;
  1108. CString csInfSection;
  1109. GUID Guid;
  1110. HKEY hkNameStore;
  1111. DebugTrace(TRACE_PROC_ENTER,(("CDevice::PostInstall: Enter... \r\n")));
  1112. //
  1113. // Initialize local.
  1114. //
  1115. bRet = FALSE;
  1116. hkRun = NULL;
  1117. dwFlagPresent = 1;
  1118. Guid = GUID_DEVCLASS_IMAGE;
  1119. hkNameStore = (HKEY)INVALID_HANDLE_VALUE;
  1120. if(IsFeatureInstallation()){
  1121. //
  1122. // This is a "feature" added to other class devnode and being installed by co-isntaller.
  1123. // Need to do actual installation here only for "feature", manual installed device would
  1124. // be installed through wizard. (final.cpp)
  1125. //
  1126. bRet = Install();
  1127. if(FALSE == bRet){
  1128. DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: device interface registry key creation failed. \r\n")));
  1129. bSucceeded = FALSE;
  1130. } //if(FALSE == bRet)
  1131. } // if(IsFeatureInstallation())
  1132. if(!bSucceeded){
  1133. HDEVINFO hDevInfo;
  1134. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  1135. DWORD dwIndex;
  1136. //
  1137. // Installation failed. Do clean up.
  1138. //
  1139. DebugTrace(TRACE_STATUS,(("CDevice::PostInstall: Installation failed. Do clean up.\r\n")));
  1140. //
  1141. // Delete craeted interface if any.
  1142. //
  1143. if(IsInterfaceOnlyDevice()){
  1144. hDevInfo = GetDeviceInterfaceIndex(m_csDeviceID, &dwIndex);
  1145. if(IS_VALID_HANDLE(hDevInfo)){
  1146. spDevInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
  1147. if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &Guid, dwIndex, &spDevInterfaceData)){
  1148. //
  1149. // Created Interface is found. Delete it...
  1150. //
  1151. DebugTrace(TRACE_STATUS,(("CDevice::PostInstall: Deleting created interface for %ws.\r\n"), (LPTSTR)m_csFriendlyName));
  1152. if(!SetupDiRemoveDeviceInterface(hDevInfo, &spDevInterfaceData)){
  1153. DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! Unable to delete interface for %ws. Err=0x%x\n"), m_csFriendlyName, GetLastError()));
  1154. }
  1155. } // if(SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &Guid, dwIndex, &spDevInterfaceData))
  1156. //
  1157. // Destroy created DevInfoSet.
  1158. //
  1159. SetupDiDestroyDeviceInfoList(hDevInfo);
  1160. } // if(NULL != hDevInfo)
  1161. } // if(IsInterfaceOnlyDevice())
  1162. bRet = TRUE;
  1163. goto PostInstall_return;
  1164. } // if(!bSucceeded)
  1165. //
  1166. // Save all Inf parameters to registry.
  1167. //
  1168. if(!UpdateDeviceRegistry()){
  1169. DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! UpdateDeviceRegistry() failed. \r\n")));
  1170. }
  1171. //
  1172. // Do WIA/STI device only process.
  1173. //
  1174. if( (!m_csSubClass.IsEmpty())
  1175. && (0 == MyStrCmpi(m_csSubClass, STILL_IMAGE)) )
  1176. {
  1177. HKEY hkeyTemp;
  1178. //
  1179. // Change service to AUTO start.
  1180. //
  1181. SetServiceStart(STI_SERVICE_NAME, SERVICE_AUTO_START);
  1182. //
  1183. // Start WIA service.
  1184. //
  1185. if(!StartWiaService()){
  1186. // DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! Unable to start WIA service.\r\n")));
  1187. }
  1188. //
  1189. // Create "Scanner and Camera Wizard" menu if WIA.
  1190. //
  1191. if(m_dwCapabilities & STI_GENCAP_WIA){
  1192. CreateWiaShortcut();
  1193. //
  1194. // Add following value upon device arrival for performance improvement.
  1195. //
  1196. if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_WIASHEXT, &hkeyTemp)) {
  1197. RegSetValue (hkeyTemp,
  1198. NULL,
  1199. REG_SZ,
  1200. REGSTR_VAL_WIASHEXT,
  1201. lstrlen(REGSTR_VAL_WIASHEXT) * sizeof(TCHAR));
  1202. RegCloseKey(hkeyTemp);
  1203. hkeyTemp = NULL;
  1204. } else {
  1205. DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! RegOpenKey(WIASHEXT) failed. Err=0x%x \r\n"), GetLastError()));
  1206. } // if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun))
  1207. } // if(m_dwCapabilities & STI_GENCAP_WIA)
  1208. //
  1209. // Also add shell's flag about WIA device presence, this should be portable
  1210. // to NT
  1211. //
  1212. if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun)) {
  1213. RegDeleteValue (hkRun, REGSTR_VAL_WIA_PRESENT);
  1214. RegSetValueEx (hkRun,
  1215. REGSTR_VAL_WIA_PRESENT,
  1216. 0,
  1217. REG_DWORD,
  1218. (LPBYTE)&dwFlagPresent,
  1219. sizeof(DWORD));
  1220. } else {
  1221. DebugTrace(TRACE_ERROR,(("CDevice::PostInstall: ERROR!! RegOpenKey() failed. Err=0x%x \r\n"), GetLastError()));
  1222. } // if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SOFT_STI, &hkRun))
  1223. //
  1224. // Notify WIA service device arrival
  1225. //
  1226. WiaDeviceEnum();
  1227. } // if(!lstrcmpi(m_csSubClass, STILL_IMAGE))
  1228. //
  1229. // ICM support
  1230. //
  1231. ProcessICMProfiles();
  1232. //
  1233. // Register interface name of Videoo device.
  1234. //
  1235. bRet = TRUE;
  1236. PostInstall_return:
  1237. //
  1238. // Clean up.
  1239. //
  1240. if(NULL != hkRun){
  1241. RegCloseKey(hkRun);
  1242. }
  1243. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::PostInstall: Leaving... Ret=0x%x.\r\n"), bRet));
  1244. return bRet;
  1245. } // CDevice::PostInstall()
  1246. BOOL
  1247. CDevice::HandleFilesInstallation(
  1248. VOID
  1249. )
  1250. /*++
  1251. Routine Description:
  1252. Arguments:
  1253. Return Value:
  1254. Side effects:
  1255. --*/
  1256. {
  1257. BOOL bRet;
  1258. BOOL bSetParamRet;
  1259. PSP_FILE_CALLBACK pSavedCallback;
  1260. PVOID pvContext;
  1261. SP_DEVINSTALL_PARAMS spDeviceInstallParams;
  1262. DebugTrace(TRACE_PROC_ENTER,(("CDevice::HandleFilesInstallation: Enter... \r\n")));
  1263. //
  1264. // Initialize local.
  1265. //
  1266. bRet = FALSE;
  1267. bSetParamRet = FALSE;
  1268. pvContext = NULL;
  1269. pSavedCallback = NULL;
  1270. memset(&spDeviceInstallParams, 0, sizeof(spDeviceInstallParams));
  1271. //
  1272. // Get device install parameter.
  1273. //
  1274. spDeviceInstallParams.cbSize = sizeof (SP_DEVINSTALL_PARAMS);
  1275. if (!SetupDiGetDeviceInstallParams (m_hDevInfo, m_pspDevInfoData, &spDeviceInstallParams)) {
  1276. DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiGetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
  1277. bRet = FALSE;
  1278. goto HandleFilesInstallation_return;
  1279. }
  1280. //
  1281. // Modify device installation parameters to have custom callback
  1282. //
  1283. pvContext = SetupInitDefaultQueueCallbackEx(NULL,
  1284. (HWND)((spDeviceInstallParams.Flags & DI_QUIETINSTALL) ?INVALID_HANDLE_VALUE : NULL),
  1285. 0,
  1286. 0,
  1287. NULL);
  1288. if(NULL == pvContext){
  1289. DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupInitDefaultQueueCallbackEx() failed. Err=0x%x.\r\n"), GetLastError()));
  1290. bRet = FALSE;
  1291. goto HandleFilesInstallation_return;
  1292. } // if(NULL == pvContext)
  1293. pSavedCallback = spDeviceInstallParams.InstallMsgHandler;
  1294. spDeviceInstallParams.InstallMsgHandler = StiInstallCallback;
  1295. spDeviceInstallParams.InstallMsgHandlerContext = pvContext;
  1296. bSetParamRet = SetupDiSetDeviceInstallParams (m_hDevInfo,
  1297. m_pspDevInfoData,
  1298. &spDeviceInstallParams);
  1299. if(FALSE == bSetParamRet){
  1300. DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
  1301. bRet = FALSE;
  1302. goto HandleFilesInstallation_return;
  1303. } // if(FALSE == bSetParamRet)
  1304. //
  1305. // Let the default installer do its job.
  1306. //
  1307. if(IsInterfaceOnlyDevice()){
  1308. bRet = CreateDeviceInterfaceAndInstall();
  1309. } else {
  1310. bRet = SetupDiInstallDevice(m_hDevInfo, m_pspDevInfoData);
  1311. }
  1312. if(FALSE == bRet){
  1313. DebugTrace(TRACE_ERROR,(("CDevice::HandleFilesInstallation: ERROR!! SetupDiInstallDevice() failed. Err=0x%x.\r\n"), GetLastError()));
  1314. bRet = FALSE;
  1315. goto HandleFilesInstallation_return;
  1316. } // if(FALSE == bSetParamRet)
  1317. //
  1318. // Terminate defaule queue callback
  1319. //
  1320. SetupTermDefaultQueueCallback(pvContext);
  1321. //
  1322. // Cleanup.
  1323. //
  1324. if (bSetParamRet) {
  1325. spDeviceInstallParams.InstallMsgHandler = pSavedCallback;
  1326. SetupDiSetDeviceInstallParams (m_hDevInfo, m_pspDevInfoData, &spDeviceInstallParams);
  1327. }
  1328. HandleFilesInstallation_return:
  1329. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::HandleFilesInstallation: Leaving... Ret=0x%x.\r\n"), bRet));
  1330. return bRet;
  1331. } // CDevice::HandleFilesInstallation()
  1332. BOOL
  1333. CDevice::UpdateDeviceRegistry(
  1334. VOID
  1335. )
  1336. {
  1337. BOOL bRet;
  1338. HKEY hkDrv;
  1339. DWORD dwConnectionType;
  1340. HINF hInf;
  1341. DebugTrace(TRACE_PROC_ENTER,(("CDevice::UpdateDeviceRegistry: Enter... \r\n")));
  1342. //
  1343. // Initialize Local.
  1344. //
  1345. bRet = FALSE;
  1346. hkDrv = NULL;
  1347. dwConnectionType = STI_HW_CONFIG_UNKNOWN;
  1348. //
  1349. // Open INF.
  1350. //
  1351. hInf = SetupOpenInfFile(m_csInf,
  1352. NULL,
  1353. INF_STYLE_WIN4,
  1354. NULL);
  1355. if (hInf == INVALID_HANDLE_VALUE) {
  1356. DebugTrace(TRACE_ERROR, (("CDevice::UpdateDeviceRegistry: Unable to open INF(%ws). Error = 0x%x.\r\n"),m_csInf, GetLastError()));
  1357. bRet = FALSE;
  1358. goto UpdateDeviceRegistry_return;
  1359. } // if (hInf == INVALID_HANDLE_VALUE)
  1360. //
  1361. // Create device registry key.
  1362. //
  1363. if(IsInterfaceOnlyDevice()){
  1364. DebugTrace(TRACE_STATUS,(("CDevice::UpdateDeviceRegistry: This is Interface-only device.\r\n")));
  1365. //
  1366. // Create interface reg-key.
  1367. //
  1368. hkDrv = m_hkInterfaceRegistry;
  1369. } else { // if(IsInterfaceOnlyDevice())
  1370. DebugTrace(TRACE_STATUS,(("CDevice::UpdateDeviceRegistry: This is devnode device.\r\n")));
  1371. hkDrv = SetupDiCreateDevRegKey(m_hDevInfo,
  1372. m_pspDevInfoData,
  1373. DICS_FLAG_GLOBAL,
  1374. 0,
  1375. DIREG_DRV,
  1376. NULL,
  1377. NULL);
  1378. } // if(IsInterfaceOnlyDevice())
  1379. if(hkDrv == INVALID_HANDLE_VALUE) {
  1380. DebugTrace(TRACE_ERROR,(("CDevice::UpdateDeviceRegistry: ERROR!! SetupDiCreateDevRegKey() failed. Err=0x%x.\r\n"), GetLastError()));
  1381. bRet = FALSE;
  1382. goto UpdateDeviceRegistry_return;
  1383. } //if(hkDrv == INVALID_HANDLE_VALUE)
  1384. //
  1385. // Save INF parameters to registry.
  1386. //
  1387. if(m_csPort.IsEmpty()){
  1388. if(m_bInterfaceOnly){
  1389. //
  1390. // If PortName doesn't exist for interface-only device, then use symbolic link as CraeteFile name.
  1391. //
  1392. m_csSymbolicLink.Store(hkDrv, CREATEFILENAME);
  1393. } //if(m_bInterfaceOnly)
  1394. } else { // if(m_csPort.IsEmpty())
  1395. m_csPort.Store(hkDrv, CREATEFILENAME);
  1396. } // if(m_csPort.IsEmpty())
  1397. m_csSubClass.Store(hkDrv, SUBCLASS);
  1398. m_csUSDClass.Store(hkDrv, USDCLASS);
  1399. m_csVendor.Store(hkDrv, VENDOR);
  1400. m_csFriendlyName.Store(hkDrv, FRIENDLYNAME);
  1401. m_csUninstallSection.Store(hkDrv, UNINSTALLSECTION);
  1402. m_csPropPages.Store(hkDrv, PROPERTYPAGES);
  1403. m_csIcmProfile.Store(hkDrv, ICMPROFILES);
  1404. m_csDeviceID.Store(hkDrv, REGSTR_VAL_DEVICE_ID);
  1405. m_csPortSelect.Store (hkDrv, PORTSELECT);
  1406. if(IsInterfaceOnlyDevice()){
  1407. m_csInf.Store(hkDrv, INFPATH);
  1408. m_csInstallSection.Store(hkDrv, INFSECTION);
  1409. m_csDriverDescription.Store(hkDrv, DRIVERDESC);
  1410. } // if(IsInterfaceOnlyDevice())
  1411. //
  1412. // Save DWORD values.
  1413. //
  1414. RegSetValueEx(hkDrv,
  1415. CAPABILITIES,
  1416. 0,
  1417. REG_DWORD,
  1418. (LPBYTE) &m_dwCapabilities,
  1419. sizeof(m_dwCapabilities));
  1420. RegSetValueEx(hkDrv,
  1421. DEVICETYPE,
  1422. 0,
  1423. REG_DWORD,
  1424. (LPBYTE) &m_dwDeviceType,
  1425. sizeof(m_dwDeviceType));
  1426. RegSetValueEx(hkDrv,
  1427. DEVICESUBTYPE,
  1428. 0,
  1429. REG_DWORD,
  1430. (LPBYTE) &m_dwDeviceSubType,
  1431. sizeof(m_dwDeviceSubType));
  1432. RegSetValueEx(hkDrv,
  1433. ISPNP,
  1434. 0,
  1435. REG_DWORD,
  1436. (LPBYTE) &m_bIsPnP,
  1437. sizeof(m_bIsPnP));
  1438. //
  1439. // Set HardwareConfig. (= Connection)
  1440. //
  1441. if(!m_csConnection.IsEmpty()){
  1442. m_csConnection.Store (hkDrv, CONNECTION);
  1443. if(_tcsicmp(m_csConnection, SERIAL) == 0 ){
  1444. dwConnectionType = STI_HW_CONFIG_SERIAL;
  1445. }
  1446. else if(_tcsicmp(m_csConnection, PARALLEL) == 0 ){
  1447. dwConnectionType = STI_HW_CONFIG_PARALLEL;
  1448. }
  1449. if (dwConnectionType != STI_HW_CONFIG_UNKNOWN) {
  1450. RegSetValueEx(hkDrv,
  1451. REGSTR_VAL_HARDWARE,
  1452. 0,
  1453. REG_DWORD,
  1454. (LPBYTE) &dwConnectionType,
  1455. sizeof(dwConnectionType));
  1456. }
  1457. } // if(!m_csConneciton.IsEmpty())
  1458. //
  1459. // Process DeviceData section.
  1460. //
  1461. ProcessDataSection(hInf, hkDrv);
  1462. //
  1463. // Process Event section.
  1464. //
  1465. ProcessEventsSection(hInf, hkDrv);
  1466. //
  1467. // Create registry key for video key if applicable.
  1468. //
  1469. ProcessVideoDevice(hkDrv);
  1470. //
  1471. // Operation succeeded.
  1472. //
  1473. bRet = TRUE;
  1474. UpdateDeviceRegistry_return:
  1475. //
  1476. // Cleanup.
  1477. //
  1478. if(hkDrv != INVALID_HANDLE_VALUE){
  1479. RegCloseKey(hkDrv);
  1480. m_hkInterfaceRegistry = NULL;
  1481. }
  1482. if(hInf != INVALID_HANDLE_VALUE){
  1483. SetupCloseInfFile(hInf);
  1484. }
  1485. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::UpdateDeviceRegistry: Leaving... Ret=0x%x.\r\n"), bRet));
  1486. return bRet;
  1487. } // CDevice::UpdateDeviceRegistry()
  1488. VOID
  1489. CDevice::ProcessVideoDevice(
  1490. HKEY hkDrv
  1491. )
  1492. {
  1493. GUID Guid;
  1494. HKEY hkDeviceData;
  1495. TCHAR Buffer[1024];
  1496. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  1497. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetail;
  1498. DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessVideoDevice: Enter... \r\n")));
  1499. //
  1500. // Initialize local.
  1501. //
  1502. Guid = KSCATEGORY_CAPTURE;
  1503. pspDevInterfaceDetail = NULL;
  1504. hkDeviceData = NULL;
  1505. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  1506. memset(Buffer, 0, sizeof(Buffer));
  1507. //
  1508. // This is only for video devices.
  1509. //
  1510. if (!m_bVideoDevice) {
  1511. DebugTrace(TRACE_STATUS,(("CDevice::ProcessVideoDevice: This is not a video device. Do nothing.\r\n")));
  1512. goto ProcessVideoDevice_return;
  1513. }
  1514. //
  1515. // Use "AUTO" as dummy CreatFile name for Video devices.
  1516. //
  1517. RegSetValueEx( hkDrv,
  1518. CREATEFILENAME,
  1519. 0,
  1520. REG_SZ,
  1521. (LPBYTE)AUTO,
  1522. (lstrlen(AUTO)+1)*sizeof(TCHAR)
  1523. );
  1524. //
  1525. // Get device interface data of installing Video device.
  1526. //
  1527. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  1528. if (!SetupDiEnumDeviceInterfaces (m_hDevInfo,
  1529. m_pspDevInfoData,
  1530. &Guid,
  1531. 0,
  1532. &spDevInterfaceData
  1533. ) )
  1534. {
  1535. DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!!SetupDiEnumDeviceInterfaces failed. Err=0x%x \r\n"), GetLastError()));
  1536. goto ProcessVideoDevice_return;
  1537. }
  1538. //
  1539. // Get detailed data of acquired interface.
  1540. //
  1541. pspDevInterfaceDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buffer;
  1542. pspDevInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  1543. if (!SetupDiGetDeviceInterfaceDetail (m_hDevInfo,
  1544. &spDevInterfaceData,
  1545. pspDevInterfaceDetail,
  1546. sizeof(Buffer) - sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA),
  1547. NULL,
  1548. NULL) )
  1549. {
  1550. DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!!SetupDiGetDeviceInterfaceDetail failed. Err=0x%x \r\n"), GetLastError()));
  1551. goto ProcessVideoDevice_return;
  1552. }
  1553. //
  1554. // We got the device path, now write it to registry
  1555. //
  1556. if (ERROR_SUCCESS != RegOpenKey(hkDrv, DEVICESECTION, &hkDeviceData)) {
  1557. DebugTrace(TRACE_ERROR,(("ProcessVideoDevice: ERROR!! Unable to open DeviceData key. Err=0x%x \r\n"), GetLastError()));
  1558. goto ProcessVideoDevice_return;
  1559. }
  1560. RegSetValueEx(hkDeviceData,
  1561. VIDEO_PATH_ID,
  1562. 0,
  1563. REG_SZ,
  1564. (LPBYTE)pspDevInterfaceDetail->DevicePath,
  1565. (lstrlen(pspDevInterfaceDetail->DevicePath)+1)*sizeof(TCHAR) );
  1566. ProcessVideoDevice_return:
  1567. //
  1568. // Cleanup.
  1569. //
  1570. if(NULL != hkDeviceData){
  1571. RegCloseKey(hkDeviceData);
  1572. }
  1573. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessVideoDevice: Leaving... Ret=VOID.\r\n")));
  1574. return;
  1575. } // CDevice::ProcessVideoDevice()
  1576. VOID
  1577. CDevice::ProcessEventsSection(
  1578. HINF hInf,
  1579. HKEY hkDrv
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. Arguments:
  1584. Return Value:
  1585. Side effects:
  1586. --*/
  1587. {
  1588. CString csFriendlyName;
  1589. CString csRegisteredApp;
  1590. CString csGuid;
  1591. HKEY hkEvents;
  1592. HKEY hkEventPod;
  1593. INFCONTEXT InfContext;
  1594. UINT uiLineIndex = 0;
  1595. BOOL fRet = TRUE;
  1596. BOOL fLooping = TRUE;
  1597. TCHAR pKeyName[LINE_LEN ];
  1598. TCHAR pField [MAX_INF_STRING_LENGTH];
  1599. TCHAR pTypeField[LINE_LEN];
  1600. DWORD dwKeySize = LINE_LEN;
  1601. DWORD dwFieldSize = MAX_INF_STRING_LENGTH;
  1602. DWORD dwError = 0;
  1603. DWORD dwFieldIndex = 0;
  1604. DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessEventsSection: Enter... \r\n")));
  1605. if (!m_csEventSection.IsEmpty()) {
  1606. // First create device data subkey
  1607. dwError = RegCreateKey(hkDrv, EVENTS, &hkEvents);
  1608. if ( NOERROR == dwError ) {
  1609. fLooping = SetupFindFirstLine(hInf,
  1610. (LPCTSTR) m_csEventSection,
  1611. NULL,
  1612. &InfContext
  1613. );
  1614. while (fLooping) {
  1615. ::ZeroMemory(pKeyName, sizeof(pKeyName));
  1616. ::ZeroMemory(pField, sizeof(pField));
  1617. ::ZeroMemory(pTypeField, sizeof(pTypeField) );
  1618. // Get key name as zero-based indexed field
  1619. dwFieldIndex = 0;
  1620. dwKeySize = sizeof(pKeyName) / sizeof(TCHAR);
  1621. fRet = SetupGetStringField(&InfContext,
  1622. dwFieldIndex,
  1623. pKeyName,
  1624. dwKeySize,
  1625. NULL);
  1626. dwError = ::GetLastError();
  1627. if (!fRet) {
  1628. // Didn't get key name - move to the next
  1629. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get key name. Error=0x%x. \r\n"), dwError));
  1630. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1631. continue;
  1632. }
  1633. // Get friendly name field
  1634. dwFieldIndex = 1;
  1635. dwFieldSize = sizeof(pField) / sizeof(TCHAR);
  1636. fRet = SetupGetStringField(&InfContext,
  1637. dwFieldIndex,
  1638. pField,
  1639. dwFieldSize,
  1640. NULL);
  1641. dwError = ::GetLastError();
  1642. if (!fRet ) {
  1643. // Didn't get name - move to the next
  1644. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError));
  1645. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1646. continue;
  1647. }
  1648. csFriendlyName = pField;
  1649. // Get GUID field
  1650. dwFieldIndex = 2;
  1651. dwFieldSize = sizeof(pField) / sizeof(TCHAR);
  1652. fRet = SetupGetStringField(&InfContext,
  1653. dwFieldIndex,
  1654. pField,
  1655. dwFieldSize,
  1656. NULL);
  1657. dwError = ::GetLastError();
  1658. if (!fRet ) {
  1659. // Didn't get GUID - move to the next line
  1660. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError));
  1661. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1662. continue;
  1663. }
  1664. csGuid = pField;
  1665. // Get registered app field
  1666. dwFieldIndex = 3;
  1667. dwFieldSize = sizeof(pField) / sizeof(TCHAR);
  1668. fRet = SetupGetStringField(&InfContext,
  1669. 3,
  1670. pField,
  1671. dwFieldSize,
  1672. NULL);
  1673. dwError = ::GetLastError();
  1674. if (fRet ) {
  1675. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Failed to get field [%d]. Error=0x%x. \r\n"), dwFieldIndex, dwError));
  1676. csRegisteredApp = pField;
  1677. }
  1678. else {
  1679. // Didn't get key type - use widlcard by default
  1680. csRegisteredApp = TEXT("*");
  1681. }
  1682. // Now only if we have all needed values - save to the registry
  1683. if (RegCreateKey(hkEvents, pKeyName, &hkEventPod) == NO_ERROR) {
  1684. // Event friendly name store as default value
  1685. csFriendlyName.Store (hkEventPod, TEXT(""));
  1686. csGuid.Store (hkEventPod, SZ_GUID);
  1687. csRegisteredApp.Store (hkEventPod, LAUNCH_APP);
  1688. RegCloseKey (hkEventPod);
  1689. } else {
  1690. // Couldn't create event key - bad
  1691. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Unable to create RegKey. Error=0x%x.\r\n"), GetLastError()));
  1692. }
  1693. // Move to the next line finally
  1694. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1695. }
  1696. RegCloseKey (hkEvents);
  1697. } else {
  1698. DebugTrace(TRACE_ERROR,(("CDevice::ProcessEventsSection: ERROR!! Unable to create event RegKey. Error=0x%x.\r\n"), GetLastError()));
  1699. }
  1700. }
  1701. // ProcessEventsSection_return:
  1702. //
  1703. // Cleanup.
  1704. //
  1705. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessEventsSection: Leaving... Ret=VOID.\r\n")));
  1706. return;
  1707. } // CDevice::ProcessEventsSection()
  1708. VOID
  1709. CDevice::ProcessDataSection(
  1710. HINF hInf,
  1711. HKEY hkDrv
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. Arguments:
  1716. Return Value:
  1717. Side effects:
  1718. --*/
  1719. {
  1720. CString csTempValue;
  1721. HKEY hkDeviceData;
  1722. INFCONTEXT InfContext;
  1723. UINT uiLineIndex = 0;
  1724. BOOL fRet = TRUE;
  1725. BOOL fLooping = TRUE;
  1726. TCHAR pKeyName[LINE_LEN ];
  1727. TCHAR pField [MAX_INF_STRING_LENGTH];
  1728. TCHAR pTypeField[LINE_LEN];
  1729. // Sizes are in characters
  1730. DWORD dwKeySize = LINE_LEN;
  1731. DWORD dwFieldSize = MAX_INF_STRING_LENGTH;
  1732. DWORD dwError = 0;
  1733. DWORD dwFieldIndex = 0;
  1734. DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessDataSection: Enter... \r\n")));
  1735. if (!m_csDataSection.IsEmpty()) {
  1736. // First create device data subkey
  1737. dwError = RegCreateKey(hkDrv, DEVICESECTION, &hkDeviceData);
  1738. if ( NOERROR == dwError ) {
  1739. // Seek to the first line of the section
  1740. fLooping = SetupFindFirstLine(hInf,
  1741. (LPCTSTR) m_csDataSection,
  1742. NULL,
  1743. &InfContext);
  1744. while (fLooping) {
  1745. dwKeySize = sizeof(pKeyName) / sizeof(TCHAR);
  1746. ::ZeroMemory(pKeyName, sizeof(pKeyName));
  1747. ::ZeroMemory(pField, sizeof(pField));
  1748. ::ZeroMemory(pTypeField, sizeof(pTypeField) );
  1749. dwFieldIndex = 0;
  1750. // Get key name as zero-indexed field
  1751. fRet = SetupGetStringField(&InfContext,
  1752. dwFieldIndex,
  1753. pKeyName,
  1754. dwKeySize,
  1755. &dwKeySize);
  1756. dwError = ::GetLastError();
  1757. if (!fRet) {
  1758. // Didn't get key name - move to the next
  1759. DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: Failed to get key name. Error = 0x%x.\r\n"),dwError));
  1760. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1761. continue;
  1762. }
  1763. // Get value field
  1764. dwFieldIndex = 1;
  1765. dwFieldSize = sizeof(pField) / sizeof(TCHAR);
  1766. fRet = SetupGetStringField(&InfContext,
  1767. dwFieldIndex,
  1768. pField,
  1769. dwFieldSize,
  1770. NULL);
  1771. dwError = ::GetLastError();
  1772. if (!fRet ) {
  1773. // Didn't get key name - move to the next
  1774. DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: Failed to get field [%d]. Error = 0x%x.\r\n"),dwFieldIndex, dwError));
  1775. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1776. continue;
  1777. }
  1778. csTempValue = pField;
  1779. // Get value field
  1780. *pTypeField = TEXT('\0');
  1781. dwFieldIndex = 2;
  1782. dwFieldSize = sizeof(pTypeField) / sizeof(TCHAR);
  1783. fRet = SetupGetStringField(&InfContext,
  1784. dwFieldIndex,
  1785. pTypeField,
  1786. dwFieldSize,
  1787. NULL);
  1788. dwError = ::GetLastError();
  1789. if (!fRet ) {
  1790. // Didn't get key type - assume string
  1791. *pTypeField = TEXT('\0');
  1792. }
  1793. // Now we have both type and value - save it in the registry
  1794. csTempValue.Store (hkDeviceData, pKeyName,pTypeField );
  1795. // Move to the next line finally
  1796. fLooping = SetupFindNextLine(&InfContext,&InfContext);
  1797. }
  1798. //
  1799. // Process migrating DeviceData section.
  1800. //
  1801. MigrateDeviceData(hkDeviceData, m_pExtraDeviceData, "");
  1802. // Now clean up
  1803. RegCloseKey (hkDeviceData);
  1804. } else { // if ( NOERROR == dwError )
  1805. DebugTrace(TRACE_ERROR, (("CDevice::ProcessDataSection: ERROR!! Unable to create DataSection RegKey. Error = 0x%x.\r\n"), dwError));
  1806. } // if ( NOERROR == dwError )
  1807. } // if (!m_csDataSection.IsEmpty())
  1808. // ProcessDataSection_return:
  1809. //
  1810. // Cleanup.
  1811. //
  1812. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::ProcessDataSection: Leaving... Ret=VOID.\r\n")));
  1813. return;
  1814. } // CDevice::ProcessDataSection()
  1815. VOID
  1816. CDevice::ProcessICMProfiles(
  1817. VOID
  1818. )
  1819. /*++
  1820. Routine Description:
  1821. Arguments:
  1822. Return Value:
  1823. Side effects:
  1824. --*/
  1825. {
  1826. DWORD Idx;
  1827. CStringArray csaICMProfiles;
  1828. TCHAR szAnsiName[STI_MAX_INTERNAL_NAME_LENGTH];
  1829. DebugTrace(TRACE_PROC_ENTER,(("CDevice::ProcessICMProfiles: Enter... \r\n")));
  1830. //
  1831. // Initialize Local.
  1832. //
  1833. Idx = 0;
  1834. memset(szAnsiName, 0, sizeof(szAnsiName));
  1835. //
  1836. // If section doesn't exist, just return.
  1837. //
  1838. if(m_csIcmProfile.IsEmpty()){
  1839. goto ProcessICMProfiles_return;
  1840. }
  1841. //
  1842. // Split a line to each token.
  1843. //
  1844. csaICMProfiles.Tokenize ((LPTSTR)m_csIcmProfile, FIELD_DELIMETER);
  1845. //
  1846. // Process all ICM profiles.
  1847. //
  1848. while ((LPTSTR)csaICMProfiles[Idx] != NULL) {
  1849. DebugTrace(TRACE_STATUS,(("ProcessICMProfiles: Installing ICM profile%d(%ws) for %ws.\r\n"), Idx, (LPTSTR)csaICMProfiles[Idx], (LPTSTR)m_csDeviceID));
  1850. //
  1851. // Install color profile.
  1852. //
  1853. if (!InstallColorProfile (NULL, csaICMProfiles[Idx])) {
  1854. DebugTrace(TRACE_ERROR,(("ProcessICMProfiles: ERROR!! InstallColorProfile failed. Err=0x%x \r\n"), GetLastError()));
  1855. } // if (!InstallColorProfile (NULL, csaICMProfiles[Idx]))
  1856. //
  1857. // Register color profile with installing device.
  1858. //
  1859. if (!AssociateColorProfileWithDevice (NULL, csaICMProfiles[Idx], (LPTSTR)m_csDeviceID)) {
  1860. DebugTrace(TRACE_ERROR,(("ProcessICMProfiles: ERROR!! AssociateColorProfileWithDevice failed. Err=0x%x \r\n"), GetLastError())); }
  1861. //
  1862. // Process next device.
  1863. //
  1864. Idx++;
  1865. } // while ((LPTSTR)csaICMProfiles[Idx] != NULL)
  1866. ProcessICMProfiles_return:
  1867. return;
  1868. } // CDevice::ProcessICMProfiles()
  1869. BOOL
  1870. CDevice::GetInfInforamtion(
  1871. VOID
  1872. )
  1873. {
  1874. BOOL bRet;
  1875. HINF hInf;
  1876. SP_DRVINFO_DATA DriverInfoData;
  1877. PSP_DRVINFO_DETAIL_DATA pDriverInfoDetailData;
  1878. TCHAR szInfSectionName[MAX_DESCRIPTION];
  1879. DWORD dwSize;
  1880. DWORD dwLastError;
  1881. DebugTrace(TRACE_PROC_ENTER,(("CDevice::GetInfInforamtion: Enter... \r\n")));
  1882. //
  1883. // Initialize locals.
  1884. //
  1885. dwSize = 0;
  1886. bRet = FALSE;
  1887. hInf = INVALID_HANDLE_VALUE;
  1888. dwLastError = ERROR_SUCCESS;
  1889. pDriverInfoDetailData = NULL;
  1890. memset (szInfSectionName, 0, sizeof(szInfSectionName));
  1891. memset (&DriverInfoData, 0, sizeof(SP_DRVINFO_DATA));
  1892. //
  1893. // Get selected device driver information.
  1894. //
  1895. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  1896. if (!SetupDiGetSelectedDriver(m_hDevInfo, m_pspDevInfoData, &DriverInfoData)) {
  1897. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetSelectedDriver Failed. Err=0x%x\r\n"), GetLastError()));
  1898. bRet = FALSE;
  1899. goto GetInfInforamtion_return;
  1900. }
  1901. //
  1902. // See required buffer size for driver detailed data.
  1903. //
  1904. SetupDiGetDriverInfoDetail(m_hDevInfo,
  1905. m_pspDevInfoData,
  1906. &DriverInfoData,
  1907. NULL,
  1908. 0,
  1909. &dwSize);
  1910. dwLastError = GetLastError();
  1911. if(ERROR_INSUFFICIENT_BUFFER != dwLastError){
  1912. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetDriverInfoDetail doesn't return required size.Er=0x%x\r\n"),dwLastError));
  1913. bRet = FALSE;
  1914. goto GetInfInforamtion_return;
  1915. }
  1916. //
  1917. // Allocate required size of buffer for driver detailed data.
  1918. //
  1919. pDriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)new char[dwSize];
  1920. if(NULL == pDriverInfoDetailData){
  1921. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! Unable to allocate driver detailed info buffer.\r\n")));
  1922. bRet = FALSE;
  1923. goto GetInfInforamtion_return;
  1924. }
  1925. //
  1926. // Initialize allocated buffer.
  1927. //
  1928. memset(pDriverInfoDetailData, 0, dwSize);
  1929. pDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  1930. //
  1931. // Get detailed data of selected device driver.
  1932. //
  1933. if(!SetupDiGetDriverInfoDetail(m_hDevInfo,
  1934. m_pspDevInfoData,
  1935. &DriverInfoData,
  1936. pDriverInfoDetailData,
  1937. dwSize,
  1938. NULL) )
  1939. {
  1940. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetDriverInfoDetail Failed.Er=0x%x\r\n"),GetLastError()));
  1941. bRet = FALSE;
  1942. goto GetInfInforamtion_return;
  1943. }
  1944. //
  1945. // Open INF file of selected driver.
  1946. //
  1947. hInf = SetupOpenInfFile(pDriverInfoDetailData->InfFileName,
  1948. NULL,
  1949. INF_STYLE_WIN4,
  1950. NULL);
  1951. if (hInf == INVALID_HANDLE_VALUE) {
  1952. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupOpenInfFile Failed.Er=0x%x\r\n"),GetLastError()));
  1953. bRet = FALSE;
  1954. goto GetInfInforamtion_return;
  1955. }
  1956. //
  1957. // Get actual INF section name to be installed.
  1958. //
  1959. if (!SetupDiGetActualSectionToInstall(hInf,
  1960. pDriverInfoDetailData->SectionName,
  1961. szInfSectionName,
  1962. sizeof(szInfSectionName)/sizeof(TCHAR),
  1963. NULL,
  1964. NULL) )
  1965. {
  1966. DebugTrace(TRACE_ERROR,(("CDevice::GetInfInforamtion: ERROR!! SetupDiGetActualSectionToInstall Failed.Er=0x%x\r\n"),GetLastError()));
  1967. bRet = FALSE;
  1968. goto GetInfInforamtion_return;
  1969. }
  1970. //
  1971. // Set Inf section/file name.
  1972. //
  1973. m_csInf = pDriverInfoDetailData->InfFileName;
  1974. m_csInstallSection = szInfSectionName;
  1975. DebugTrace(TRACE_STATUS,(("CDevice::GetInfInforamtion: INF Filename : %ws\n"),(LPTSTR)m_csInf));
  1976. DebugTrace(TRACE_STATUS,(("CDevice::GetInfInforamtion: INF Section name: %ws\n"),(LPTSTR)m_csInstallSection));
  1977. //
  1978. // Operation succeeded.
  1979. //
  1980. bRet = TRUE;
  1981. GetInfInforamtion_return:
  1982. //
  1983. // Clean up.
  1984. //
  1985. if(INVALID_HANDLE_VALUE != hInf){
  1986. SetupCloseInfFile(hInf);
  1987. }
  1988. if(NULL != pDriverInfoDetailData){
  1989. delete[] pDriverInfoDetailData;
  1990. }
  1991. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::GetInfInforamtion: Leaving... Ret=0x%x\n"), bRet));
  1992. return bRet;
  1993. } // CDevice::GetInfInforamtion()
  1994. VOID
  1995. CDevice::SetPort(
  1996. LPTSTR szPortName
  1997. )
  1998. {
  1999. DebugTrace(TRACE_STATUS,(("CDevice::SetPort: Current Portname=%ws\n"), szPortName));
  2000. //
  2001. // Set PortName.
  2002. //
  2003. m_csPort = szPortName;
  2004. } // CDevice::SetPort()
  2005. VOID
  2006. CDevice::SetFriendlyName(
  2007. LPTSTR szFriendlyName
  2008. )
  2009. //
  2010. // Note:
  2011. // Before calling this function, caller has to make sure mutex is acquired.
  2012. //
  2013. {
  2014. HKEY hkNameStore;
  2015. //
  2016. // Mutex must have been acquired before this call.
  2017. //
  2018. DebugTrace(TRACE_STATUS,(("CDevice::SetFriendlyName: Current CreateFileName=%ws\n"), szFriendlyName));
  2019. //
  2020. // Delete stored entry, create new one.
  2021. //
  2022. if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){
  2023. HKEY hkTemp;
  2024. hkTemp = (HKEY)INVALID_HANDLE_VALUE;
  2025. //
  2026. // Delete FriendlyName and DeviceId in name store.
  2027. //
  2028. RegDeleteKey(hkNameStore, m_csFriendlyName);
  2029. if(ERROR_SUCCESS == RegCreateKey(hkNameStore, szFriendlyName, &hkTemp)){
  2030. RegCloseKey(hkTemp);
  2031. } // if(ERROR_SUCCESS == RegCreateKey(hkNameStore, szFriendlyName, &hkTemp))
  2032. RegCloseKey(hkNameStore);
  2033. } // if(ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore))
  2034. //
  2035. // Set PortName.
  2036. //
  2037. m_csFriendlyName = szFriendlyName;
  2038. } // CDevice::SetPort()
  2039. VOID
  2040. CDevice::SetDevnodeSelectCallback(
  2041. DEVNODESELCALLBACK pfnDevnodeSelCallback
  2042. )
  2043. {
  2044. DebugTrace(TRACE_STATUS,(("CDevice::SetDevnodeSelectCallback: Current PortselCallback=0x%x\n"), pfnDevnodeSelCallback));
  2045. //
  2046. // Set SetPortselCallBack.
  2047. //
  2048. m_pfnDevnodeSelCallback = pfnDevnodeSelCallback;
  2049. //
  2050. // This is "interface-only" device.
  2051. //
  2052. m_bInterfaceOnly = TRUE;
  2053. } // CDevice::SetDevnodeSelectCallback()
  2054. BOOL
  2055. CDevice::CreateDeviceInterfaceAndInstall(
  2056. VOID
  2057. )
  2058. {
  2059. BOOL bRet;
  2060. HKEY hkDrv;
  2061. GUID Guid;
  2062. HDEVINFO hDevInfo;
  2063. SP_DEVINFO_DATA spDevInfoData;
  2064. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  2065. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  2066. HINF hInf;
  2067. BOOL bUseDefaultDevInfoSet;
  2068. DWORD dwRequiredSize;
  2069. DebugTrace(TRACE_PROC_ENTER,(("CDevice::CreateDeviceInterfaceAndInstall: Enter....\r\n")));
  2070. //
  2071. // Initialize local.
  2072. //
  2073. bRet = FALSE;
  2074. hInf = INVALID_HANDLE_VALUE;
  2075. hDevInfo = INVALID_HANDLE_VALUE;
  2076. Guid = GUID_DEVCLASS_IMAGE;
  2077. bUseDefaultDevInfoSet = TRUE;
  2078. dwRequiredSize = 0;
  2079. pspDevInterfaceDetailData = NULL;
  2080. //
  2081. // Get devnode to create interface on.
  2082. //
  2083. if(NULL != m_pfnDevnodeSelCallback){
  2084. if( (FALSE == m_pfnDevnodeSelCallback(m_csPort, &hDevInfo, &spDevInfoData))
  2085. || (INVALID_HANDLE_VALUE == hDevInfo) )
  2086. {
  2087. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: m_pfnDevnodeSelCallback failed. Err=0x%x.\r\n"),GetLastError()));
  2088. bRet = FALSE;
  2089. goto CreateDeviceInterfaceAndInstall_return;
  2090. }
  2091. //
  2092. // Devnode selector functions.
  2093. //
  2094. bUseDefaultDevInfoSet = FALSE;
  2095. } else { // if(NULL != m_pfnDevnodeSelCallback)
  2096. //
  2097. // Use default device info set if available.
  2098. //
  2099. if( (INVALID_HANDLE_VALUE == m_hDevInfo)
  2100. || (NULL == m_pspDevInfoData) )
  2101. {
  2102. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Invalid Device info and no m_pfnDevnodeSelCallback.\r\n")));
  2103. bRet = FALSE;
  2104. goto CreateDeviceInterfaceAndInstall_return;
  2105. } else {
  2106. hDevInfo = m_hDevInfo;
  2107. spDevInfoData = *m_pspDevInfoData;
  2108. }
  2109. } // if(NULL != m_pfnDevnodeSelCallback)
  2110. //
  2111. // Create Interface (SoftDevice). Use FriendlyName ad ref-string.
  2112. //
  2113. DebugTrace(TRACE_STATUS,(("CDevice::CreateDeviceInterfaceAndInstall: Creating interface for %ws.\r\n"), (LPTSTR)m_csFriendlyName));
  2114. spDevInterfaceData.cbSize = sizeof(spDevInterfaceData);
  2115. if(!SetupDiCreateDeviceInterface(hDevInfo,
  2116. &spDevInfoData,
  2117. &Guid,
  2118. m_csFriendlyName,
  2119. 0,
  2120. &spDevInterfaceData))
  2121. {
  2122. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiCreateInterface failed. Err=0x%x.\r\n"),GetLastError()));
  2123. bRet = FALSE;
  2124. goto CreateDeviceInterfaceAndInstall_return;
  2125. }
  2126. //
  2127. // Get symbolic link of created interface.
  2128. //
  2129. SetupDiGetDeviceInterfaceDetail(hDevInfo,
  2130. &spDevInterfaceData,
  2131. NULL,
  2132. 0,
  2133. &dwRequiredSize,
  2134. NULL);
  2135. if(0 == dwRequiredSize){
  2136. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Unable to get required size for InterfaceDetailedData. Err=0x%x.\r\n"),GetLastError()));
  2137. bRet = FALSE;
  2138. goto CreateDeviceInterfaceAndInstall_return;
  2139. } // if(0 == dwRequiredSize)
  2140. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[dwRequiredSize];
  2141. if(NULL == pspDevInterfaceDetailData){
  2142. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: Unable to allocate buffer.\r\n")));
  2143. bRet = FALSE;
  2144. goto CreateDeviceInterfaceAndInstall_return;
  2145. } // if(NULL == pspDevInterfaceDetailData)
  2146. pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  2147. if(!SetupDiGetDeviceInterfaceDetail(hDevInfo,
  2148. &spDevInterfaceData,
  2149. pspDevInterfaceDetailData,
  2150. dwRequiredSize,
  2151. &dwRequiredSize,
  2152. NULL))
  2153. {
  2154. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiGetDeviceInterfaceDetail() failed. Err=0x%x.\r\n"),GetLastError()));
  2155. bRet = FALSE;
  2156. goto CreateDeviceInterfaceAndInstall_return;
  2157. } // if(!SetupDiGetDeviceInterfaceDetail(
  2158. m_csSymbolicLink = pspDevInterfaceDetailData->DevicePath;
  2159. //
  2160. // Open INF file handle for registry creation.
  2161. //
  2162. hInf = SetupOpenInfFile(m_csInf,
  2163. NULL,
  2164. INF_STYLE_WIN4,
  2165. NULL);
  2166. if(INVALID_HANDLE_VALUE == hInf){
  2167. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupOpenInfFile failed. Err=0x%x.\r\n"),GetLastError()));
  2168. bRet = FALSE;
  2169. goto CreateDeviceInterfaceAndInstall_return;
  2170. } // if(INVALID_HANDLE_VALUE == hInf)
  2171. if(!SetupOpenAppendInfFile(NULL, hInf, NULL)){
  2172. DebugTrace(TRACE_WARNING,(("CDevice::CreateDeviceInterfaceAndInstall: SetupOpenAppendInfFile() failed. Err=0x%x.\r\n"),GetLastError()));
  2173. } // if(!SetupOpenAppendInfFile(NULL, hInf, NULL))
  2174. //
  2175. // Create Interface Registry and keep its handle, it's hard to find it later.
  2176. //
  2177. m_hkInterfaceRegistry = SetupDiCreateDeviceInterfaceRegKey(hDevInfo,
  2178. &spDevInterfaceData,
  2179. 0,
  2180. KEY_ALL_ACCESS,
  2181. // NULL,
  2182. // NULL);
  2183. hInf,
  2184. (LPCTSTR)m_csInstallSection);
  2185. if(INVALID_HANDLE_VALUE == m_hkInterfaceRegistry){
  2186. DebugTrace(TRACE_ERROR,(("CDevice::CreateDeviceInterfaceAndInstall: SetupDiCreateDeviceInterfaceRegKey failed. Err=0x%x.\r\n"),GetLastError()));
  2187. bRet = FALSE;
  2188. goto CreateDeviceInterfaceAndInstall_return;
  2189. } // if(INVALID_HANDLE_VALUE == m_hkInterfaceRegistry)
  2190. //
  2191. // Operation succeeded.
  2192. //
  2193. bRet = TRUE;
  2194. CreateDeviceInterfaceAndInstall_return:
  2195. //
  2196. // Clean up.
  2197. //
  2198. if(INVALID_HANDLE_VALUE != hDevInfo){
  2199. if(FALSE == bUseDefaultDevInfoSet){
  2200. //
  2201. // Destroy created DevInfoSet.
  2202. //
  2203. SetupDiDestroyDeviceInfoList(hDevInfo);
  2204. } // if(FALSE == bUseDefaultDevInfoSet)
  2205. } // if(INVALID_HANDLE_VALUE != hDevInfo)
  2206. if(INVALID_HANDLE_VALUE != hInf){
  2207. SetupCloseInfFile(hInf);
  2208. } // if(INVALID_HANDLE_VALUE != hInf)
  2209. if(NULL != pspDevInterfaceDetailData){
  2210. delete[] pspDevInterfaceDetailData;
  2211. } // if(NULL != pspDevInterfaceDetailData)
  2212. DebugTrace(TRACE_PROC_LEAVE,(("CDevice::CreateDeviceInterfaceAndInstall: Leaving... Ret=0x%x.\r\n"), bRet));
  2213. return bRet;
  2214. } // CDevice::CreateDeviceInterfaceAndInstall()
  2215. DWORD
  2216. CDevice::GetPortSelectMode(
  2217. VOID
  2218. )
  2219. {
  2220. DWORD dwRet;
  2221. //
  2222. // Initialize local.
  2223. //
  2224. dwRet = PORTSELMODE_NORMAL;
  2225. //
  2226. // Make sure INF is processed.
  2227. //
  2228. if(!PreprocessInf()){
  2229. DebugTrace(TRACE_ERROR,(("CDevice::GetPortSelectMode: ERROR!! Unable to process INF.\r\n")));
  2230. dwRet = PORTSELMODE_NORMAL;
  2231. goto GetPortSelectMode_return;
  2232. }
  2233. //
  2234. // If "PortSelect" is empty, use default.
  2235. //
  2236. if(m_csPortSelect.IsEmpty()){
  2237. dwRet = PORTSELMODE_NORMAL;
  2238. goto GetPortSelectMode_return;
  2239. } // if(m_csPortSelect.IsEmpty())
  2240. //
  2241. // See if "PortSelect" directive is "no".
  2242. //
  2243. if(0 == MyStrCmpi(m_csPortSelect, NO)){
  2244. //
  2245. // Port Selection page should be skipped.
  2246. //
  2247. dwRet = PORTSELMODE_SKIP;
  2248. } else if(0 == MyStrCmpi(m_csPortSelect, MESSAGE1)){
  2249. //
  2250. // System supplied message should be shown.
  2251. //
  2252. dwRet = PORTSELMODE_MESSAGE1;
  2253. } else {
  2254. //
  2255. // Unsupported PortSel option.
  2256. //
  2257. dwRet = PORTSELMODE_NORMAL;
  2258. }
  2259. GetPortSelectMode_return:
  2260. return dwRet;
  2261. } // CDevice::GetPortSelectMode()
  2262. DWORD
  2263. CDevice::AcquireInstallerMutex(
  2264. DWORD dwTimeout
  2265. )
  2266. {
  2267. DWORD dwReturn;
  2268. //
  2269. // Initialize local.
  2270. //
  2271. dwReturn = ERROR_SUCCESS;
  2272. if(NULL != m_hMutex){
  2273. //
  2274. // Mutex is already acquired.
  2275. //
  2276. DebugTrace(TRACE_WARNING,("WARNING!! AcquireInstallerMutex: Mutex acquired twice.\r\n"));
  2277. dwReturn = ERROR_SUCCESS;
  2278. goto AcquireInstallerMutex_return;
  2279. } // if(INVALID_HANDLE_VALUE != m_hMutex)
  2280. //
  2281. // Acquire Mutex.
  2282. //
  2283. m_hMutex = CreateMutex(NULL, FALSE, WIAINSTALLERMUTEX);
  2284. dwReturn = GetLastError();
  2285. if(NULL == m_hMutex){
  2286. //
  2287. // CreteMutex() failed.
  2288. //
  2289. DebugTrace(TRACE_ERROR,("ERROR!! AcquireInstallerMutex: CraeteMutex() failed. Err=0x%x.\r\n", dwReturn));
  2290. goto AcquireInstallerMutex_return;
  2291. } // if(NULL == hMutex)
  2292. //
  2293. // Wait until ownership is acquired.
  2294. //
  2295. dwReturn = WaitForSingleObject(m_hMutex, dwTimeout);
  2296. switch(dwReturn){
  2297. case WAIT_ABANDONED:
  2298. DebugTrace(TRACE_ERROR, ("CDevice::AcquireInstallerMutex: ERROR!! Wait abandoned.\r\n"));
  2299. break;
  2300. case WAIT_OBJECT_0:
  2301. DebugTrace(TRACE_STATUS, ("CDevice::AcquireInstallerMutex: Mutex acquired.\r\n"));
  2302. dwReturn = ERROR_SUCCESS;
  2303. break;
  2304. case WAIT_TIMEOUT:
  2305. DebugTrace(TRACE_WARNING, ("CDevice::AcquireInstallerMutex: WARNING!! Mutex acquisition timeout.\r\n"));
  2306. break;
  2307. default:
  2308. DebugTrace(TRACE_ERROR, ("CDevice::AcquireInstallerMutex: ERROR!! Unexpected error from WaitForSingleObjecct(). Err=0x%x.\r\n", dwReturn));
  2309. break;
  2310. } // switch(dwReturn)
  2311. AcquireInstallerMutex_return:
  2312. DebugTrace(TRACE_PROC_LEAVE,("CDevice::AcquireInstallerMutex: Leaving... Ret=0x%x\n", dwReturn));
  2313. return dwReturn;
  2314. } // CDevice::AcquireInstallerMutex()
  2315. VOID
  2316. CDevice::ReleaseInstallerMutex(
  2317. )
  2318. {
  2319. if(NULL != m_hMutex){
  2320. if(!ReleaseMutex(m_hMutex)){
  2321. DebugTrace(TRACE_ERROR, ("CDevice::ReleaseInstallerMutex: ERROR!! Releasing mutex which not owned..\r\n"));
  2322. } // if(!ReleaseMutex(m_hMutex))
  2323. CloseHandle(m_hMutex);
  2324. m_hMutex = NULL;
  2325. DebugTrace(TRACE_STATUS, ("CDevice::ReleaseInstallerMutex: Mutex released.\r\n"));
  2326. } // if(NULL != m_hMutex)
  2327. } // CDevice::ReleaseInstallerMutex()
  2328. UINT
  2329. CALLBACK
  2330. StiInstallCallback (
  2331. PVOID Context,
  2332. UINT Notification,
  2333. UINT_PTR Param1,
  2334. UINT_PTR Param2
  2335. )
  2336. /*++
  2337. Routine Description:
  2338. StiInstallCallback
  2339. Callback routine used when calling SetupAPI file copying/installation functions
  2340. Arguments:
  2341. Context - our context
  2342. Notification - notification message
  2343. Return Value:
  2344. SetupAPI return code
  2345. Side effects:
  2346. None
  2347. --*/
  2348. {
  2349. UINT uRet = FILEOP_COPY;
  2350. DebugTrace(TRACE_PROC_ENTER,(("StiInstallCallback: Enter... \r\n")));
  2351. //
  2352. // Initialize local.
  2353. //
  2354. uRet = FILEOP_COPY;
  2355. //
  2356. // Dispatch notification code.
  2357. //
  2358. switch(Notification){
  2359. case SPFILENOTIFY_ENDCOPY:
  2360. {
  2361. PFILEPATHS pFilePathInfo;
  2362. HKEY hKey;
  2363. DWORD dwDisposition;
  2364. DWORD dwRefCount;
  2365. DWORD dwType;
  2366. UINT uSize;
  2367. LONG Status;
  2368. uSize = sizeof(dwRefCount);
  2369. pFilePathInfo = (PFILEPATHS)Param1;
  2370. DebugTrace(TRACE_STATUS,(("StiInstallCallback:ENDCOPY FileTarget %ws\r\n"), pFilePathInfo->Target));
  2371. //
  2372. // Open HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDlls
  2373. //
  2374. Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  2375. REGSTR_PATH_SHAREDDLL,
  2376. 0,
  2377. NULL,
  2378. REG_OPTION_NON_VOLATILE,
  2379. KEY_ALL_ACCESS,
  2380. NULL,
  2381. &hKey,
  2382. &dwDisposition);
  2383. if(ERROR_SUCCESS != Status)
  2384. {
  2385. DebugTrace(TRACE_ERROR,(("StiInstallCallback: RegCreateKeyEx failed. Err=0x%x\r\n"), Status));
  2386. break;
  2387. }
  2388. //
  2389. // Retrieve reference count of this file
  2390. //
  2391. Status = RegQueryValueEx(hKey,
  2392. pFilePathInfo->Target,
  2393. NULL,
  2394. &dwType,
  2395. (LPBYTE)&dwRefCount,
  2396. (LPDWORD)&uSize);
  2397. if(ERROR_SUCCESS != Status)
  2398. {
  2399. //
  2400. // Value for this file hasn't been created, or error
  2401. //
  2402. DebugTrace(TRACE_ERROR,(("StiInstallCallback: Value for Ref-count doesn't exist\r\n")));
  2403. dwRefCount = 0;
  2404. }
  2405. //
  2406. // Increment reference count and set value
  2407. //
  2408. dwRefCount++;
  2409. uSize = sizeof(dwRefCount);
  2410. Status = RegSetValueEx(hKey,
  2411. pFilePathInfo->Target,
  2412. NULL,
  2413. REG_DWORD,
  2414. (CONST BYTE *)&dwRefCount,
  2415. uSize);
  2416. if(ERROR_SUCCESS != Status)
  2417. {
  2418. DebugTrace(TRACE_ERROR,(("StiInstallCallback: RegSetValueEx. Err=0x%x.\r\n"), Status));
  2419. }
  2420. DebugTrace(TRACE_STATUS,(("StiInstallCallback: ref-count of %ws is now 0x%x.\r\n"), pFilePathInfo->Target, dwRefCount));
  2421. //
  2422. // Close Registry key
  2423. //
  2424. RegCloseKey(hKey);
  2425. Report(( TEXT("StiInstallCallback:%ws copied.\r\n"), pFilePathInfo->Target));
  2426. } // case SPFILENOTIFY_ENDCOPY
  2427. default:
  2428. ;
  2429. }
  2430. uRet = SetupDefaultQueueCallback(Context,
  2431. Notification,
  2432. Param1,
  2433. Param2);
  2434. DebugTrace(TRACE_PROC_LEAVE,(("StiInstallCallback: Leaving... Ret=0x%x\n"), uRet));
  2435. return uRet;
  2436. }
  2437. VOID
  2438. GetDeviceCount(
  2439. DWORD *pdwWiaCount,
  2440. DWORD *pdwStiCount
  2441. )
  2442. /*++
  2443. Routine Description:
  2444. GetDeviceCount
  2445. Verifes if there is at least one STI device installed in a system
  2446. Arguments:
  2447. bWia - TRUE: Count WIA device
  2448. Return Value:
  2449. Number of WIA device
  2450. FALSE
  2451. --*/
  2452. {
  2453. DWORD dwWiaCount;
  2454. DWORD dwStiCount;
  2455. BOOL fRet;
  2456. CString csSubClass;
  2457. DWORD dwCapabilities;
  2458. GUID Guid;
  2459. UINT Idx;
  2460. DWORD dwRequired;
  2461. DWORD dwError;
  2462. HKEY hkThis;
  2463. HKEY hkRun;
  2464. HANDLE hDevInfo;
  2465. SP_DEVINFO_DATA spDevInfoData;
  2466. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  2467. DebugTrace(TRACE_PROC_ENTER,(("GetDeviceCount: Enter... \r\n")));
  2468. //
  2469. // Initialize local.
  2470. //
  2471. dwWiaCount = 0;
  2472. dwStiCount = 0;
  2473. fRet = FALSE;
  2474. Idx = 0;
  2475. dwRequired = 0;
  2476. dwError = 0;
  2477. hkThis = NULL;
  2478. hkRun = NULL;
  2479. hDevInfo = NULL;
  2480. dwCapabilities = 0;
  2481. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  2482. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  2483. //
  2484. // Get WIA class guid.
  2485. //
  2486. SetupDiClassGuidsFromName (CLASSNAME, &Guid, sizeof(GUID), &dwRequired);
  2487. //
  2488. // Get device info set of all WIA devices (devnode).
  2489. //
  2490. hDevInfo = SetupDiGetClassDevs (&Guid,
  2491. NULL,
  2492. NULL,
  2493. DIGCF_PROFILE
  2494. );
  2495. if (hDevInfo != INVALID_HANDLE_VALUE) {
  2496. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  2497. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  2498. #if DEBUG
  2499. CHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
  2500. ULONG cbData;
  2501. fRet = SetupDiGetDeviceRegistryProperty (hDevInfo,
  2502. &spDevInfoData,
  2503. SPDRP_DRIVER,
  2504. NULL,
  2505. (UCHAR *)szDevDriver, sizeof (szDevDriver),
  2506. &cbData);
  2507. DebugTrace(TRACE_STATUS,(("GetDeviceCount: Checking device No%d(%ws)\r\n"), Idx, szDevDriver));
  2508. #endif
  2509. //
  2510. // Verify device is not being removed
  2511. //
  2512. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2513. spDevInterfaceData.InterfaceClassGuid = GUID_DEVCLASS_IMAGE;
  2514. fRet = SetupDiEnumDeviceInterfaces (hDevInfo,
  2515. NULL,
  2516. &Guid,
  2517. Idx,
  2518. &spDevInterfaceData);
  2519. dwError = GetLastError();
  2520. if (fRet) {
  2521. if (spDevInterfaceData.Flags & SPINT_REMOVED) {
  2522. continue;
  2523. }
  2524. }
  2525. hkThis = SetupDiOpenDevRegKey(hDevInfo,
  2526. &spDevInfoData,
  2527. DICS_FLAG_GLOBAL,
  2528. 0,
  2529. DIREG_DRV,
  2530. KEY_READ );
  2531. if (hkThis != INVALID_HANDLE_VALUE) {
  2532. csSubClass.Load(hkThis, SUBCLASS);
  2533. GetDwordFromRegistry(hkThis, CAPABILITIES, &dwCapabilities);
  2534. DebugTrace(TRACE_STATUS,(("GetDeviceCount: Capabilities=0x%x\n"), dwCapabilities));
  2535. RegCloseKey(hkThis);
  2536. if( (!csSubClass.IsEmpty())
  2537. && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) )
  2538. {
  2539. //
  2540. // STI device found. Increse the counter.
  2541. //
  2542. dwStiCount++;
  2543. if(dwCapabilities & STI_GENCAP_WIA){
  2544. //
  2545. // WIA device found.
  2546. //
  2547. dwWiaCount++;
  2548. } // if(dwCapabilities & STI_GENCAP_WIA){
  2549. } // if (!csSubClass.IsEmpty() && !lstrcmpi(csSubClass, STILL_IMAGE))
  2550. } // if (hkThis != INVALID_HANDLE_VALUE)
  2551. } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  2552. SetupDiDestroyDeviceInfoList(hDevInfo);
  2553. } else {
  2554. DebugTrace(TRACE_ERROR,(("GetDeviceCount: ERROR!! Unable to get device info set.\r\n")));
  2555. } // if (hDevInfo != INVALID_HANDLE_VALUE)
  2556. //
  2557. // Get device info set of all WIA devices (interface).
  2558. //
  2559. hDevInfo = SetupDiGetClassDevs (&Guid,
  2560. NULL,
  2561. NULL,
  2562. DIGCF_PROFILE |
  2563. DIGCF_DEVICEINTERFACE
  2564. );
  2565. if (hDevInfo != INVALID_HANDLE_VALUE) {
  2566. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  2567. for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) {
  2568. DebugTrace(TRACE_STATUS,(("GetDeviceCount: Checking interface No%d.\r\n"), Idx));
  2569. //
  2570. // Verify device is not being removed
  2571. //
  2572. if (spDevInterfaceData.Flags & SPINT_REMOVED) {
  2573. continue;
  2574. }
  2575. hkThis = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  2576. &spDevInterfaceData,
  2577. 0,
  2578. KEY_READ );
  2579. if (hkThis != INVALID_HANDLE_VALUE) {
  2580. csSubClass.Load(hkThis, SUBCLASS);
  2581. GetDwordFromRegistry(hkThis, CAPABILITIES, &dwCapabilities);
  2582. RegCloseKey(hkThis);
  2583. if( (!csSubClass.IsEmpty())
  2584. && (0 == MyStrCmpi(csSubClass, STILL_IMAGE)) )
  2585. {
  2586. //
  2587. // STI device found. Increse the counter.
  2588. //
  2589. dwStiCount++;
  2590. if(dwCapabilities & STI_GENCAP_WIA){
  2591. //
  2592. // WIA device found.
  2593. //
  2594. dwWiaCount++;
  2595. } // if(dwCapabilities & STI_GENCAP_WIA){
  2596. } // if (!csSubClass.IsEmpty() && !lstrcmpi(csSubClass, STILL_IMAGE))
  2597. } // if (hkThis != INVALID_HANDLE_VALUE)
  2598. } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  2599. SetupDiDestroyDeviceInfoList(hDevInfo);
  2600. } else { // if (hDevInfo != INVALID_HANDLE_VALUE)
  2601. DebugTrace(TRACE_ERROR,(("GetDeviceCount: ERROR!! Unable to get device info set.\r\n")));
  2602. } // if (hDevInfo != INVALID_HANDLE_VALUE)
  2603. //
  2604. // Copy the result.
  2605. //
  2606. *pdwWiaCount = dwWiaCount;
  2607. *pdwStiCount = dwStiCount;
  2608. DebugTrace(TRACE_PROC_LEAVE,(("GetDeviceCount: Leaving... STI=0x%x, WIA=0x%x.\r\n"), dwStiCount, dwWiaCount));
  2609. return;
  2610. } // GetDeviceCount()
  2611. BOOL
  2612. ExecCommandLine(
  2613. LPTSTR szCommandLine
  2614. )
  2615. {
  2616. BOOL bRet;
  2617. CString csCommandLine;
  2618. PROCESS_INFORMATION pi;
  2619. STARTUPINFO si = {
  2620. sizeof(si), // cb
  2621. NULL, // lpReserved;
  2622. NULL, // lpDesktop;
  2623. NULL, // lpTitle;
  2624. 0, // dwX;
  2625. 0, // dwY;
  2626. 0, // dwXSize;
  2627. 0, // dwYSize;
  2628. 0, // dwXCountChars;
  2629. 0, // dwYCountChars;
  2630. 0, // dwFillAttribute;
  2631. STARTF_FORCEONFEEDBACK, // dwFlags;
  2632. SW_SHOWNORMAL, // wShowWindow;
  2633. 0, // cbReserved2;
  2634. NULL, // lpReserved2;
  2635. NULL, // hStdInput;
  2636. NULL, // hStdOutput;
  2637. NULL // hStdError;
  2638. };
  2639. csCommandLine = szCommandLine;
  2640. bRet = CreateProcess(NULL, // Application name
  2641. (LPTSTR)csCommandLine, // Command line
  2642. NULL, // Process attributes
  2643. NULL, // Thread attributes
  2644. FALSE, // Handle inheritance
  2645. NORMAL_PRIORITY_CLASS, // Creation flags
  2646. NULL, // Environment
  2647. NULL, // Current directory
  2648. &si,
  2649. &pi);
  2650. if (bRet) {
  2651. CloseHandle(pi.hProcess);
  2652. CloseHandle(pi.hThread);
  2653. } else {
  2654. DebugTrace(TRACE_ERROR,(("ExecCommandLine: CreateProcess failed. Err=0x%x.\r\n"), GetLastError()));
  2655. }
  2656. return bRet;
  2657. }
  2658. PPARAM_LIST
  2659. MigrateDeviceData(
  2660. HKEY hkDeviceData,
  2661. PPARAM_LIST pExtraDeviceData,
  2662. LPSTR pszKeyName
  2663. )
  2664. {
  2665. BOOL bDone;
  2666. PPARAM_LIST pCurrent;
  2667. PPARAM_LIST pReturn;
  2668. DWORD dwType;
  2669. DWORD dwSize;
  2670. PCHAR pOrginalBuffer;
  2671. CHAR pCopyBuffer[MAX_PATH*3];
  2672. CHAR pDataBuffer[MAX_PATH];
  2673. DWORD Idx;
  2674. //
  2675. // Initialize local.
  2676. //
  2677. bDone = FALSE;
  2678. pCurrent = pExtraDeviceData;
  2679. pReturn = NULL;
  2680. //
  2681. // Loop until it gets "END".
  2682. //
  2683. while(!bDone){
  2684. if(NULL == pCurrent){
  2685. //
  2686. // Hit the end of list.
  2687. //
  2688. bDone = TRUE;
  2689. pReturn =NULL;
  2690. continue;
  2691. } // if(NULL == pTemp)
  2692. //
  2693. // If "KeyName = END" is found, return.
  2694. //
  2695. if( (CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam1, -1,pszKeyName,-1))
  2696. && (CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam2, -1,NAME_END_A,-1)) )
  2697. {
  2698. bDone = TRUE;
  2699. pReturn = (PPARAM_LIST)pCurrent->pNext;
  2700. continue;
  2701. }
  2702. //
  2703. // If 2nd parameter is "BEGIN", create subkey and call this function recursively.
  2704. //
  2705. if(CSTR_EQUAL == CompareStringA(LOCALE_INVARIANT,NORM_IGNORECASE, pCurrent->pParam2, -1,NAME_BEGIN_A,-1)){
  2706. HKEY hkSubKey;
  2707. LONG lError;
  2708. lError = RegCreateKeyA(hkDeviceData, pCurrent->pParam1, &hkSubKey);
  2709. if(ERROR_SUCCESS != lError){
  2710. //
  2711. // Unable to create subkey.
  2712. //
  2713. DebugTrace(TRACE_ERROR,(("MigrateDeviceData: ERROR!! Unable to create subkey..\r\n")));
  2714. pReturn = NULL;
  2715. goto MigrateDeviceData_return;
  2716. } // if(ERROR_SUCCESS != lError)
  2717. pCurrent = MigrateDeviceData(hkSubKey, (PPARAM_LIST)pCurrent->pNext, pCurrent->pParam1);
  2718. RegCloseKey(hkSubKey);
  2719. continue;
  2720. } // if(0 == lstrcmpiA(pCurrent->pParam2, NAME_BEGIN_A))
  2721. //
  2722. // This is a set of value and data.
  2723. //
  2724. lstrcpyA(pCopyBuffer, pCurrent->pParam2);
  2725. pOrginalBuffer = pCopyBuffer;
  2726. //
  2727. // Get key type.
  2728. //
  2729. pOrginalBuffer[8] = '\0';
  2730. dwType = DecodeHexA(pOrginalBuffer);
  2731. //
  2732. // Get data.
  2733. //
  2734. Idx = 0;
  2735. pOrginalBuffer+=9;
  2736. while('\0' != *pOrginalBuffer){
  2737. if('\0' != pOrginalBuffer[2]){
  2738. pOrginalBuffer[2] = '\0';
  2739. pDataBuffer[Idx++] = (CHAR)DecodeHexA(pOrginalBuffer);
  2740. pOrginalBuffer+=3;
  2741. } else {
  2742. pDataBuffer[Idx++] = (CHAR)DecodeHexA(pOrginalBuffer);
  2743. break;
  2744. }
  2745. } // while('\0' != pCurrent->pParam2[Idx])
  2746. //
  2747. // Create this value.
  2748. //
  2749. RegSetValueExA(hkDeviceData,
  2750. pCurrent->pParam1,
  2751. 0,
  2752. dwType,
  2753. (PBYTE)pDataBuffer,
  2754. Idx);
  2755. //
  2756. // Process next line.
  2757. //
  2758. pCurrent = (PPARAM_LIST)pCurrent->pNext;
  2759. } // while(!bDone)
  2760. MigrateDeviceData_return:
  2761. return pReturn;
  2762. } // MigrateDeviceData()
  2763. DWORD
  2764. DecodeHexA(
  2765. LPSTR lpstr
  2766. )
  2767. {
  2768. DWORD dwReturn;
  2769. //
  2770. // Initialize local.
  2771. //
  2772. dwReturn = 0;
  2773. if(NULL == lpstr){
  2774. dwReturn = 0;
  2775. goto DecodeHexA_return;
  2776. } // if(NULL == lpstr)
  2777. //
  2778. // Skip spaces.
  2779. //
  2780. for (LPSTR lpstrThis = lpstr;
  2781. *lpstrThis && *lpstrThis == TEXT(' ');
  2782. lpstrThis++)
  2783. ;
  2784. while (*lpstrThis) {
  2785. switch (*lpstrThis) {
  2786. case '0':
  2787. case '1':
  2788. case '2':
  2789. case '3':
  2790. case '4':
  2791. case '5':
  2792. case '6':
  2793. case '7':
  2794. case '8':
  2795. case '9':
  2796. dwReturn <<= 4;
  2797. dwReturn += ((*lpstrThis) - '0');
  2798. break;
  2799. case 'a':
  2800. case 'b':
  2801. case 'c':
  2802. case 'd':
  2803. case 'e':
  2804. case 'f':
  2805. dwReturn <<= 4;
  2806. dwReturn += 10 + (*lpstrThis - 'a');
  2807. break;
  2808. case 'A':
  2809. case 'B':
  2810. case 'C':
  2811. case 'D':
  2812. case 'E':
  2813. case 'F':
  2814. dwReturn <<= 4;
  2815. dwReturn += 10 + (*lpstrThis - 'A');
  2816. break;
  2817. default:
  2818. return dwReturn;
  2819. }
  2820. lpstrThis++;
  2821. } // while (*lpstrThis)
  2822. DecodeHexA_return:
  2823. return dwReturn;
  2824. } // DWORD CString::DecodeHex()
  2825. BOOL
  2826. IsNameAlreadyStored(
  2827. LPTSTR szName
  2828. )
  2829. {
  2830. BOOL bRet;
  2831. HKEY hkNameStore;
  2832. DebugTrace(TRACE_PROC_ENTER,(("IsNameAlreadyStored: Enter... \r\n")));
  2833. //
  2834. // Initialize local.
  2835. //
  2836. bRet = FALSE;
  2837. hkNameStore = (HKEY)INVALID_HANDLE_VALUE;
  2838. //
  2839. // Open name store regkey.
  2840. //
  2841. if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore)){
  2842. HKEY hkTemp;
  2843. hkTemp = (HKEY)INVALID_HANDLE_VALUE;
  2844. //
  2845. // See if specified name exists in name store.
  2846. //
  2847. if(ERROR_SUCCESS == RegOpenKey(hkNameStore, szName, &hkTemp)){
  2848. //
  2849. // Specified name already exists in name store.
  2850. //
  2851. bRet = TRUE;
  2852. RegCloseKey(hkTemp);
  2853. } // if(ERROR_SUCCESS == RegOpenKey(hkNameStore, szName, &hkTemp))
  2854. RegCloseKey(hkNameStore);
  2855. } // if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_NAMESTORE, &hkNameStore))
  2856. // IsNameAlreadyStored_return:
  2857. DebugTrace(TRACE_PROC_LEAVE,(("IsNameAlreadyStored: Leaving... Ret=0x%x\n"), bRet));
  2858. return bRet;
  2859. } // IsFriendlyNameUnique()
  2860. #if DEAD_CODE
  2861. #ifdef USE_STIMON
  2862. //
  2863. // For the time being always load and start the monitor
  2864. //
  2865. HKEY hkRun;
  2866. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
  2867. CString csCmdLine;
  2868. csCmdLine.MakeSystemPath(MONITOR_NAME);
  2869. csCmdLine.Store (hkRun, REGSTR_VAL_MONITOR);
  2870. Report(( TEXT("Monitor Command Line %ws\r\n"), (LPCTSTR)csCmdLine));
  2871. // Launch it...
  2872. WinExec(csCmdLine, SW_SHOWNOACTIVATE);
  2873. RegCloseKey(hkRun);
  2874. }
  2875. #endif
  2876. #endif