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.

2153 lines
60 KiB

  1. /******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: Exports.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: KeisukeT
  10. *
  11. * DATE: 27 Mar, 2000
  12. *
  13. * DESCRIPTION:
  14. * Exported functions.
  15. *
  16. *
  17. *******************************************************************************/
  18. //
  19. // Precompiled header
  20. //
  21. #include "precomp.h"
  22. #pragma hdrstop
  23. //
  24. // Include
  25. //
  26. #include "sti_ci.h"
  27. #include "exports.h"
  28. #include "device.h"
  29. #include "portsel.h"
  30. #include <devguid.h>
  31. #include <stdio.h>
  32. #include <shlobj.h>
  33. #include <objbase.h>
  34. #include <icm.h>
  35. #include <stiregi.h>
  36. #include <stisvc.h>
  37. #include <wia.h>
  38. #include <wiapriv.h>
  39. //
  40. // Global
  41. //
  42. extern HINSTANCE g_hDllInstance;
  43. //
  44. // Function
  45. //
  46. DLLEXPORT
  47. HANDLE
  48. WINAPI
  49. WiaAddDevice(
  50. VOID
  51. )
  52. {
  53. TCHAR CommandLine[MAX_COMMANDLINE];
  54. //
  55. // On NT, const string can't be the argument.
  56. //
  57. lstrcpy(CommandLine, STR_ADD_DEVICE);
  58. return WiaInstallerProcess(CommandLine);
  59. }
  60. DLLEXPORT
  61. BOOL
  62. WINAPI
  63. WiaRemoveDevice(
  64. PSTI_DEVICE_INFORMATION pStiDeviceInformation
  65. )
  66. {
  67. if(NULL == pStiDeviceInformation){
  68. DebugTrace(TRACE_ERROR,(("WiaRemoveDevice: ERROR!! Invalid argument.\r\n")));
  69. return FALSE;
  70. } // if(NULL == pStiDeviceInformation)
  71. return (RemoveDevice(NULL, g_hDllInstance, pStiDeviceInformation->szDeviceInternalName, 0));
  72. } // WiaRemoveDevice(
  73. HANDLE
  74. WiaInstallerProcess(
  75. LPTSTR lpCommandLine
  76. )
  77. {
  78. BOOL bRet = FALSE;
  79. HANDLE hProcess = NULL;
  80. PROCESS_INFORMATION ProcessInfo;
  81. STARTUPINFO SetupInfo = {sizeof SetupInfo, NULL, NULL, NULL, 0, 0,
  82. 0, 0, 0, 0, 0, STARTF_FORCEONFEEDBACK,
  83. SW_SHOWNORMAL, 0, NULL, NULL, NULL, NULL};
  84. //
  85. // Create install wizard process.
  86. //
  87. DebugTrace(TRACE_STATUS,(("WiaInstallerProcess: Executing \"%ws\".\r\n"), lpCommandLine));
  88. bRet = CreateProcess(NULL,
  89. lpCommandLine,
  90. NULL,
  91. NULL,
  92. FALSE,
  93. NORMAL_PRIORITY_CLASS,
  94. NULL,
  95. NULL,
  96. &SetupInfo,
  97. &ProcessInfo);
  98. if(bRet){
  99. DebugTrace(TRACE_STATUS,(("WiaInstallerProcess: Installer process successfully created.\r\n")));
  100. CloseHandle(ProcessInfo.hThread);
  101. hProcess = ProcessInfo.hProcess;
  102. } else {
  103. DebugTrace(TRACE_ERROR,(("WiaInstallerProcess: ERROR!! Unable to create a process. Err=0x%x.\r\n"), GetLastError()));
  104. hProcess = NULL;
  105. }
  106. return hProcess;
  107. }
  108. DLLEXPORT
  109. BOOL
  110. WINAPI
  111. CreateWiaShortcut(
  112. VOID
  113. )
  114. {
  115. HRESULT hres;
  116. IShellLink *psl;
  117. LONG err;
  118. HKEY khWindowsCurrentVersion;
  119. DWORD dwType;
  120. DWORD dwSize;
  121. TCHAR pszSystemPath[MAX_PATH]; // path to system32 folder.
  122. TCHAR pszShortcutPath[MAX_PATH]; // path to creating shortcut.
  123. TCHAR pszProgramPath[MAX_PATH]; // path to ProgramFiles folder.
  124. TCHAR pszAccessoriesPath[MAX_PATH]; // path to Accessories folder.
  125. TCHAR pszWizardPath[MAX_PATH]; // path to wiaacmgr.exe.
  126. TCHAR pszSticiPath[MAX_PATH]; // path to sti_ci.dll.
  127. TCHAR pszWizardName[MAX_PATH]; // Menu name ofcreating shortcut.
  128. TCHAR pszWizardLinkName[MAX_PATH]; // filename ofcreating shortcut.
  129. TCHAR pszWizardDesc[MAX_PATH]; // description of creating shortcut.
  130. TCHAR pszAccessoriesName[MAX_PATH]; // localized "Accessories" folder name.
  131. BOOL bRet;
  132. //
  133. // Init locals.
  134. //
  135. bRet = FALSE;
  136. psl = NULL;
  137. err = 0;
  138. khWindowsCurrentVersion = NULL;
  139. //
  140. // Get path to the "ProgramFiles" folder.
  141. //
  142. hres = SHGetFolderPath(NULL,
  143. CSIDL_COMMON_PROGRAMS | CSIDL_FLAG_CREATE,
  144. NULL,
  145. 0,
  146. pszProgramPath);
  147. if(!SUCCEEDED(hres)){
  148. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! Can't get ProgramFiles folder.\r\n")));
  149. bRet = FALSE;
  150. goto CreateWiaShortcut_return;
  151. }
  152. //
  153. // Get localized "Accessoies" folder name from reistry.
  154. //
  155. err = RegOpenKey(HKEY_LOCAL_MACHINE,
  156. REGKEY_WINDOWS_CURRENTVERSION,
  157. &khWindowsCurrentVersion);
  158. if(ERROR_SUCCESS != err){
  159. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! Can't open Windows\\CurrentVersion.Err=0x%x \r\n"), err));
  160. bRet = FALSE;
  161. goto CreateWiaShortcut_return;
  162. }
  163. dwSize = sizeof(pszAccessoriesName);
  164. err = RegQueryValueEx(khWindowsCurrentVersion,
  165. REGSTR_VAL_ACCESSORIES_NAME,
  166. NULL,
  167. &dwType,
  168. (LPBYTE)pszAccessoriesName,
  169. &dwSize);
  170. if(err){
  171. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! Can't get %ws value.Err=0x%x\r\n"), REGSTR_VAL_ACCESSORIES_NAME, err));
  172. //
  173. // Unable to get "Accessories" name from registry. Let's take it from resource.
  174. //
  175. if( (NULL == g_hDllInstance)
  176. || (0 == LoadString(g_hDllInstance, LocalAccessoriesFolderName, pszAccessoriesName, MAX_PATH)) )
  177. {
  178. bRet = FALSE;
  179. goto CreateWiaShortcut_return;
  180. } // if(0 == LoadString(g_hDllInstance, AccessoriesFolderName, pszAccessoriesName, MAX_PATH))
  181. } // if(err)
  182. //
  183. // Load localizable string from resource.
  184. //
  185. if(NULL != g_hDllInstance){
  186. LoadString(g_hDllInstance, WiaWizardName, pszWizardName, MAX_PATH);
  187. } else {
  188. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! No DLL instance\r\n")));
  189. bRet = FALSE;
  190. goto CreateWiaShortcut_return;
  191. }
  192. //
  193. // Get System path.
  194. //
  195. if( 0== GetSystemDirectory(pszSystemPath, MAX_PATH)){
  196. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! GetSystemDirectory failed. Err=0x%x\r\n"), GetLastError()));
  197. bRet = FALSE;
  198. goto CreateWiaShortcut_return;
  199. }
  200. //
  201. // Create shortcut/program name.
  202. //
  203. wsprintf(pszAccessoriesPath, TEXT("%ws\\%ws"), pszProgramPath, pszAccessoriesName);
  204. wsprintf(pszWizardLinkName, TEXT("%ws.lnk"), WIAWIZARDCHORCUTNAME);
  205. wsprintf(pszShortcutPath, TEXT("%ws\\%ws"), pszAccessoriesPath, pszWizardLinkName);
  206. wsprintf(pszWizardPath, TEXT("%ws\\%ws"), pszSystemPath, WIAACMGR_PATH);
  207. wsprintf(pszSticiPath, TEXT("%ws\\%ws"), pszSystemPath, WIAINSTALLERFILENAME);
  208. wsprintf(pszWizardDesc, TEXT("@%ws,-%d"), pszSticiPath, WiaWizardDescription);
  209. //
  210. // Create an IShellLink object and get a pointer to the IShellLink
  211. // interface (returned from CoCreateInstance).
  212. //
  213. hres = CoInitialize(NULL);
  214. if(!SUCCEEDED(hres)){
  215. DebugTrace(TRACE_ERROR,(("CoInitialize failed. hres=0x%x\r\n"), hres));
  216. bRet = FALSE;
  217. goto CreateWiaShortcut_return;
  218. }
  219. hres = CoCreateInstance(CLSID_ShellLink,
  220. NULL,
  221. CLSCTX_INPROC_SERVER,
  222. IID_IShellLink,
  223. (LPVOID *)&psl);
  224. if (SUCCEEDED(hres)){
  225. IPersistFile *ppf;
  226. //
  227. // Query IShellLink for the IPersistFile interface for
  228. // saving the shortcut in persistent storage.
  229. //
  230. hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  231. if (SUCCEEDED(hres)){
  232. // Set the path to the shortcut target.
  233. hres = psl->SetPath(pszWizardPath);
  234. if (SUCCEEDED(hres)){
  235. // Set the argument to the shortcut target.
  236. hres = psl->SetArguments(WIAACMGR_ARG);
  237. if (SUCCEEDED(hres)){
  238. // Set the description of the shortcut.
  239. hres = psl->SetDescription(pszWizardDesc);
  240. if (SUCCEEDED(hres)){
  241. // Save the shortcut via the IPersistFile::Save member function.
  242. hres = ppf->Save(pszShortcutPath, TRUE);
  243. if (SUCCEEDED(hres)){
  244. //
  245. // Shortcut created. Set MUI name.
  246. //
  247. hres = SHSetLocalizedName(pszShortcutPath, pszSticiPath, WiaWizardName);
  248. if (SUCCEEDED(hres)){
  249. //
  250. // Operation succeeded.
  251. //
  252. bRet = TRUE;
  253. } else {
  254. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! SHSetLocalizedName failed. hRes=0x%x\r\n"), hres));
  255. }
  256. } else {
  257. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! Save failed. hRes=0x%x\r\n"), hres));
  258. }
  259. } else {
  260. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! SetDescription failed. hRes=0x%x\r\n"), hres));
  261. }
  262. } else {
  263. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! SetArguments failed. hRes=0x%x\r\n"), hres));
  264. }
  265. } else {
  266. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! SetPath failed. hRes=0x%x\r\n"), hres));
  267. }
  268. // Release the pointer to IPersistFile.
  269. ppf->Release();
  270. } else {
  271. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! QueryInterface(IID_IPersistFile) failed.\r\n")));
  272. }
  273. // Release the pointer to IShellLink.
  274. psl->Release();
  275. CoUninitialize();
  276. } else { // if (SUCCEEDED(hres))
  277. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: ERROR!! CoCreateInstance(IID_IShellLink) failed.\r\n")));
  278. switch(hres){
  279. case REGDB_E_CLASSNOTREG :
  280. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: REGDB_E_CLASSNOTREG.\r\n")));
  281. break;
  282. case CLASS_E_NOAGGREGATION :
  283. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: CLASS_E_NOAGGREGATION.\r\n")));
  284. break;
  285. case E_NOINTERFACE :
  286. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: E_NOINTERFACE.\r\n")));
  287. break;
  288. default:
  289. DebugTrace(TRACE_ERROR,(("CreateWiaShortcut: default.(hres=0x%x).\r\n hres=0x%x"), hres));
  290. break;
  291. }
  292. bRet = FALSE;
  293. goto CreateWiaShortcut_return;
  294. } // if (SUCCEEDED(hres))
  295. CreateWiaShortcut_return:
  296. if(FALSE == bRet){
  297. CString csCmdLine;
  298. //
  299. // Try it again after next reboot.
  300. //
  301. csCmdLine.MakeSystemPath(STI_CI32_ENTRY_WIZMANU);
  302. csCmdLine = TEXT(" ") + csCmdLine;
  303. csCmdLine = RUNDLL32 + csCmdLine;
  304. SetRunonceKey(REGSTR_VAL_WIZMENU, csCmdLine);
  305. } // if(FALSE == bRet)
  306. //
  307. // Clean up
  308. //
  309. if(NULL != khWindowsCurrentVersion){
  310. RegCloseKey(khWindowsCurrentVersion);
  311. }
  312. return bRet;
  313. }
  314. DLLEXPORT
  315. BOOL
  316. WINAPI
  317. DeleteWiaShortcut(
  318. VOID
  319. )
  320. {
  321. HRESULT hres;
  322. IShellLink *psl;
  323. LONG err;
  324. HKEY khWindowsCurrentVersion;
  325. DWORD dwType;
  326. DWORD dwSize;
  327. TCHAR pszSystemPath[MAX_PATH];
  328. TCHAR pszShortcutPath[MAX_PATH];
  329. TCHAR pszAccessoriesName[MAX_PATH]; // localized "Accessories" folder name.
  330. TCHAR pszProgramPath[MAX_PATH]; // path to ProgramFiles folder.
  331. BOOL bRet;
  332. //
  333. // Init locals.
  334. //
  335. bRet = FALSE;
  336. psl = NULL;
  337. err = 0;
  338. khWindowsCurrentVersion = NULL;
  339. //
  340. // Get path to the "ProgramFiles" folder.
  341. //
  342. hres = SHGetFolderPath(NULL,
  343. CSIDL_COMMON_PROGRAMS | CSIDL_FLAG_CREATE,
  344. NULL,
  345. 0,
  346. pszProgramPath);
  347. if(!SUCCEEDED(hres)){
  348. DebugTrace(TRACE_ERROR,(("DeleteWiaShortcut: ERROR!! Can't get ProgramFiles folder.\r\n"), hres));
  349. bRet = FALSE;
  350. goto DeleteWiaShortcut_return;
  351. }
  352. //
  353. // Get localized "Accessoies" folder name from reistry.
  354. //
  355. err = RegOpenKey(HKEY_LOCAL_MACHINE,
  356. REGKEY_WINDOWS_CURRENTVERSION,
  357. &khWindowsCurrentVersion);
  358. if(err){
  359. DebugTrace(TRACE_ERROR,(("DeleteWiaShortcut: ERROR!! Can't open Windows\\CurrentVersion key.Err=0x%x\r\n"), err));
  360. bRet = FALSE;
  361. goto DeleteWiaShortcut_return;
  362. }
  363. dwSize = sizeof(pszAccessoriesName);
  364. err = RegQueryValueEx(khWindowsCurrentVersion,
  365. REGSTR_VAL_ACCESSORIES_NAME,
  366. NULL,
  367. &dwType,
  368. (LPBYTE)pszAccessoriesName,
  369. &dwSize);
  370. if(err){
  371. DebugTrace(TRACE_ERROR,(("DeleteWiaShortcut: ERROR!! Can't get %ws value.Err=0x%x\r\n"), REGSTR_VAL_ACCESSORIES_NAME, err));
  372. //
  373. // Unable to get "Accessories" name from registry. Let's take it from resource.
  374. //
  375. if( (NULL == g_hDllInstance)
  376. || (0 == LoadString(g_hDllInstance, LocalAccessoriesFolderName, pszAccessoriesName, MAX_PATH)) )
  377. {
  378. bRet = FALSE;
  379. goto DeleteWiaShortcut_return;
  380. } // if(0 == LoadString(g_hDllInstance, AccessoriesFolderName, pszAccessoriesName, MAX_PATH))
  381. }
  382. //
  383. // Create shortcut/program name.
  384. //
  385. wsprintf(pszShortcutPath, TEXT("%ws\\%ws\\%ws.lnk"), pszProgramPath, pszAccessoriesName, WIAWIZARDCHORCUTNAME);
  386. if(!DeleteFile((LPCTSTR)pszShortcutPath)){
  387. DebugTrace(TRACE_ERROR,(("ERROR!! DeleteFile failed. Err=0x%x\r\n"), GetLastError()));
  388. bRet = FALSE;
  389. goto DeleteWiaShortcut_return;
  390. }
  391. //
  392. // Operation succeeded.
  393. //
  394. bRet = TRUE;
  395. DeleteWiaShortcut_return:
  396. //
  397. // Clean up
  398. //
  399. if(NULL != khWindowsCurrentVersion){
  400. RegCloseKey(khWindowsCurrentVersion);
  401. }
  402. return bRet;
  403. }
  404. DLLEXPORT
  405. VOID
  406. CALLBACK
  407. WiaCreateWizardMenu(
  408. HWND hwnd,
  409. HINSTANCE hinst,
  410. LPTSTR lpszCmdLine,
  411. int nCmdShow
  412. )
  413. {
  414. CreateWiaShortcut();
  415. }
  416. DLLEXPORT
  417. VOID
  418. CALLBACK
  419. AddDevice(
  420. HWND hWnd,
  421. HINSTANCE hInst,
  422. LPSTR lpszCmdLine,
  423. int nCmdShow
  424. )
  425. {
  426. HANDLE hDevInfo;
  427. HWND hDlg;
  428. GUID Guid;
  429. SP_DEVINFO_DATA spDevInfoData;
  430. SP_INSTALLWIZARD_DATA InstallWizard;
  431. SP_DEVINSTALL_PARAMS spDevInstallParams;
  432. TCHAR ClassName[LINE_LEN];
  433. DWORD err;
  434. DWORD dwRequired;
  435. HANDLE hMutex;
  436. CString csTitle;
  437. CString csSubTitle;
  438. CString csInstruction;
  439. CString csListLabel;
  440. DebugTrace(TRACE_PROC_ENTER,(("AddDevice: Enter...\r\n")));
  441. //
  442. // Initialize locals.
  443. //
  444. hDevInfo = INVALID_HANDLE_VALUE;
  445. hDlg = hWnd;
  446. Guid = GUID_DEVCLASS_IMAGE;
  447. err = ERROR_SUCCESS;
  448. dwRequired = 0;
  449. hMutex = NULL;
  450. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  451. memset(&InstallWizard, 0, sizeof(InstallWizard));
  452. memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
  453. memset(ClassName, 0, sizeof(ClassName));
  454. //
  455. // Acquire Mutex.
  456. //
  457. CInstallerMutex CMutex(&hMutex, WIAINSTALLWIZMUTEX, 0);
  458. if(!CMutex.Succeeded()){
  459. HWND hwndAnotherWizard;
  460. CString csWindowTitle;
  461. hwndAnotherWizard = NULL;
  462. //
  463. // Other instance is running. Just activate that window and quit.
  464. //
  465. csWindowTitle.FromTable (MessageTitle);
  466. hwndAnotherWizard = FindWindow(NULL, (LPTSTR)csWindowTitle);
  467. if(NULL != hwndAnotherWizard){
  468. if(!SetForegroundWindow(hwndAnotherWizard)){
  469. DebugTrace(TRACE_ERROR, ("AddDevice: ERROR!! SetForegroundWindow() failed. Err=0x%x.\r\n", GetLastError()));
  470. } // if(!SetForegroundWindow(hwndAnotherWizard))
  471. } else { // if(NULL != hwndAnotherWizard)
  472. //
  473. // Mutex acquisition was failed but didn't find Window.
  474. // Continue.
  475. //
  476. DebugTrace(TRACE_WARNING, ("AddDevice: WARNING!! Mutex acquisition was failed but didn't find Window.\r\n"));
  477. } // else (NULL != hwndAnotherWizard)
  478. goto AddDevice_Err;
  479. } // if(!CMutex.Succeeded())
  480. //
  481. // Create Device Information Set from guid.
  482. //
  483. hDevInfo = SetupDiCreateDeviceInfoList(&Guid, hDlg);
  484. if (hDevInfo == INVALID_HANDLE_VALUE) {
  485. err=GetLastError();
  486. goto AddDevice_Err;
  487. }
  488. // //
  489. // // Get class install parameter.
  490. // //
  491. //
  492. // if(!SetupDiGetClassInstallParams(hDevInfo,
  493. // NULL,
  494. // &spSelectDeviceParams.ClassInstallHeader,
  495. // sizeof(spSelectDeviceParams),
  496. // &dwRequired)){
  497. // err=GetLastError();
  498. // goto AddDevice_Err;
  499. // }
  500. //
  501. // Get class name from Guid.
  502. //
  503. if(!SetupDiClassNameFromGuid(&Guid,
  504. ClassName,
  505. sizeof(ClassName)/sizeof(TCHAR),
  506. NULL
  507. )){
  508. err=GetLastError();
  509. goto AddDevice_Err;
  510. }
  511. //
  512. // Create a new device information element to install
  513. //
  514. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  515. if(!SetupDiCreateDeviceInfo(hDevInfo,
  516. ClassName,
  517. &Guid,
  518. NULL,
  519. hDlg,
  520. DICD_GENERATE_ID,
  521. &spDevInfoData
  522. )){
  523. err=GetLastError();
  524. goto AddDevice_Err;
  525. }
  526. //
  527. // Set new element as selected device
  528. //
  529. if(!SetupDiSetSelectedDevice(hDevInfo,
  530. &spDevInfoData
  531. )){
  532. err=GetLastError();
  533. goto AddDevice_Err;
  534. }
  535. //
  536. // Get device install parameters
  537. //
  538. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  539. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  540. &spDevInfoData,
  541. &spDevInstallParams
  542. )){
  543. err=GetLastError();
  544. goto AddDevice_Err;
  545. }
  546. //
  547. // Set device install parameters
  548. //
  549. spDevInstallParams.Flags |= DI_SHOWOEM ;
  550. spDevInstallParams.Flags |= DI_USECI_SELECTSTRINGS;
  551. spDevInstallParams.hwndParent = hDlg;
  552. if(!SetupDiSetDeviceInstallParams(hDevInfo,
  553. &spDevInfoData,
  554. &spDevInstallParams
  555. )){
  556. err=GetLastError();
  557. goto AddDevice_Err;
  558. }
  559. //
  560. // Set class install parameter.
  561. //
  562. InstallWizard.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD;
  563. InstallWizard.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  564. InstallWizard.hwndWizardDlg = hDlg;
  565. //
  566. // TRUE = Show first page
  567. //
  568. InstallWizard.PrivateFlags = SCIW_PRIV_CALLED_FROMCPL | SCIW_PRIV_SHOW_FIRST;
  569. if(!SetupDiSetClassInstallParams(hDevInfo,
  570. &spDevInfoData,
  571. &InstallWizard.ClassInstallHeader,
  572. sizeof(SP_INSTALLWIZARD_DATA)
  573. ))
  574. {
  575. err=GetLastError();
  576. goto AddDevice_Err;
  577. }
  578. //
  579. // Call class installer to retrieve wizard pages
  580. //
  581. if(!SetupDiCallClassInstaller(DIF_INSTALLWIZARD,
  582. hDevInfo,
  583. &spDevInfoData
  584. )){
  585. err=GetLastError();
  586. goto AddDevice_Err;
  587. }
  588. //
  589. // Get result from class installer
  590. //
  591. if(!SetupDiGetClassInstallParams(hDevInfo,
  592. &spDevInfoData,
  593. &InstallWizard.ClassInstallHeader,
  594. sizeof(SP_INSTALLWIZARD_DATA),
  595. NULL
  596. ))
  597. {
  598. err=GetLastError();
  599. goto AddDevice_Err;
  600. }
  601. //
  602. // Prepare UI parameters to be used by DevSelect page,
  603. //
  604. csTitle.FromTable(SelDevTitle);
  605. csSubTitle.FromTable(SelDevSubTitle);
  606. csInstruction.FromTable(SelDevInstructions);
  607. csListLabel.FromTable(SelDevListLabel);
  608. if(!SetSelectDevTitleAndInstructions(hDevInfo,
  609. &spDevInfoData,
  610. (LPTSTR)csTitle,
  611. (LPTSTR)csSubTitle,
  612. (LPTSTR)csInstruction,
  613. (LPTSTR)csListLabel))
  614. {
  615. err=GetLastError();
  616. goto AddDevice_Err;
  617. }
  618. //
  619. // Get device selection page
  620. //
  621. InstallWizard.DynamicPageFlags = DYNAWIZ_FLAG_PAGESADDED;
  622. InstallWizard.DynamicPages[InstallWizard.NumDynamicPages++] = SetupDiGetWizardPage(hDevInfo,
  623. &spDevInfoData,
  624. &InstallWizard,
  625. SPWPT_SELECTDEVICE,
  626. 0);
  627. //
  628. // Create installer property sheet
  629. //
  630. {
  631. PROPSHEETHEADER PropSheetHeader;
  632. DWORD Pages;
  633. HPROPSHEETPAGE SelectDevicePage;
  634. PropSheetHeader.dwSize = sizeof(PropSheetHeader);
  635. PropSheetHeader.dwFlags = PSH_WIZARD | PSH_USECALLBACK | PSH_WIZARD97 | PSH_STRETCHWATERMARK | PSH_WATERMARK | PSH_HEADER;
  636. PropSheetHeader.pszbmWatermark = MAKEINTRESOURCE(WizardBitmap);
  637. PropSheetHeader.pszbmHeader = MAKEINTRESOURCE(IDB_BANNERBMP);
  638. PropSheetHeader.hwndParent = hDlg;
  639. PropSheetHeader.hInstance = g_hDllInstance;
  640. PropSheetHeader.pszIcon = NULL; //MAKEINTRESOURCE(IDI_NEWDEVICEICON);
  641. PropSheetHeader.pszCaption = MAKEINTRESOURCE(MessageTitle);
  642. PropSheetHeader.nStartPage = 0;
  643. PropSheetHeader.nPages = InstallWizard.NumDynamicPages;
  644. PropSheetHeader.phpage = InstallWizard.DynamicPages;
  645. PropSheetHeader.pfnCallback = iHdwWizardDlgCallback;
  646. if(PropertySheet(&PropSheetHeader) < 0){
  647. err=GetLastError();
  648. }
  649. }
  650. AddDevice_Err:
  651. //
  652. // Free allocated memory
  653. //
  654. if(IS_VALID_HANDLE(hDevInfo)){
  655. //
  656. // Set install parameter.
  657. //
  658. InstallWizard.ClassInstallHeader.InstallFunction = DIF_DESTROYWIZARDDATA;
  659. InstallWizard.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  660. if(!SetupDiSetClassInstallParams(hDevInfo,
  661. &spDevInfoData,
  662. &InstallWizard.ClassInstallHeader,
  663. sizeof(SP_INSTALLWIZARD_DATA)) )
  664. {
  665. DebugTrace(TRACE_ERROR,(("AddDevice: ERROR!! SetupDiSetClassInstallParams() failed with active hDevInfo.\r\n")));
  666. }
  667. //
  668. // Let isntaller free context data.
  669. //
  670. SetupDiCallClassInstaller(DIF_DESTROYWIZARDDATA,
  671. hDevInfo,
  672. &spDevInfoData
  673. );
  674. //
  675. // Destroy infoset.
  676. //
  677. SetupDiDestroyDeviceInfoList(hDevInfo);
  678. }
  679. DebugTrace(TRACE_PROC_LEAVE,(("AddDevice: Leaving... Ret=VOID.\r\n")));
  680. return;
  681. }
  682. BOOL
  683. CALLBACK
  684. RemoveDevice(
  685. HWND hWnd,
  686. HINSTANCE hInst,
  687. LPTSTR lpszCmdLine,
  688. int nCmdShow
  689. )
  690. {
  691. HANDLE hDevInfo;
  692. SP_DEVINFO_DATA spDevInfoData;
  693. SP_REMOVEDEVICE_PARAMS spRemoveDeviceParams;
  694. BOOL bStatus;
  695. BOOL bIsInterfaceOnly;
  696. DWORD err;
  697. DWORD dwDeviceIndex;
  698. TCHAR szTemp[MAX_FRIENDLYNAME+1];
  699. DebugTrace(TRACE_PROC_ENTER,(("RemoveDevice: Enter...\r\n")));
  700. //
  701. // Initialize local.
  702. //
  703. hDevInfo = INVALID_HANDLE_VALUE;
  704. bStatus = FALSE;
  705. err = ERROR_SUCCESS;
  706. bIsInterfaceOnly = FALSE;
  707. dwDeviceIndex = INVALID_DEVICE_INDEX;
  708. memset (&spDevInfoData, 0, sizeof(SP_DEVINFO_DATA));
  709. memset((void *)&spRemoveDeviceParams, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
  710. //
  711. // Check the argument.
  712. //
  713. if(NULL == lpszCmdLine){
  714. DebugTrace(TRACE_ERROR,(("RemoveDevice: ERROR!! Invalid argumet.\r\n")));
  715. goto RemoveDevice_Err;
  716. } // if(NULL == lpszCmdLine)
  717. lstrcpy(szTemp, lpszCmdLine);
  718. DebugTrace(TRACE_STATUS,(("RemoveDevice: Removing \"%ws\".\r\n"), szTemp));
  719. //
  720. // Get removing device element.
  721. //
  722. hDevInfo = SelectDevInfoFromDeviceId(szTemp);
  723. if(INVALID_HANDLE_VALUE != hDevInfo){
  724. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  725. SetupDiGetSelectedDevice(hDevInfo, &spDevInfoData);
  726. } else {
  727. //
  728. // See if it's "Interface-only" device.
  729. //
  730. hDevInfo = GetDeviceInterfaceIndex(szTemp, &dwDeviceIndex);
  731. if( (INVALID_HANDLE_VALUE == hDevInfo)
  732. || (INVALID_DEVICE_INDEX == dwDeviceIndex) )
  733. {
  734. DebugTrace(TRACE_ERROR,(("RemoveDevice: ERROR!! Can't find \"%ws\".\r\n"), szTemp));
  735. goto RemoveDevice_Err;
  736. }
  737. //
  738. // This is "Interface-only" device.
  739. //
  740. bIsInterfaceOnly = TRUE;
  741. } // if(INVALID_HANDLE_VALUE != hDevInfo)
  742. if(bIsInterfaceOnly){
  743. DebugTrace(TRACE_STATUS,(("RemoveDevice: Uninstalling interface-only device.\r\n")));
  744. //
  745. // Uninstalling "Interface-only" device.
  746. //
  747. CDevice cdThis(hDevInfo, dwDeviceIndex);
  748. bStatus = (NO_ERROR == cdThis.Remove(NULL));
  749. } else { // if(bIsInterfaceOnly)
  750. DebugTrace(TRACE_STATUS,(("RemoveDevice: Uninstalling a device w/ devnode.\r\n")));
  751. //
  752. // Uninstalling device w/ devnode.
  753. //
  754. if(!SetupDiSetSelectedDevice(hDevInfo,
  755. &spDevInfoData
  756. )){
  757. err=GetLastError();
  758. goto RemoveDevice_Err;
  759. }
  760. //
  761. // Call class installer to remove selected device.
  762. //
  763. spRemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
  764. spRemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  765. spRemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL;
  766. if(!SetupDiSetClassInstallParams(hDevInfo,
  767. &spDevInfoData,
  768. &spRemoveDeviceParams.ClassInstallHeader,
  769. sizeof(SP_REMOVEDEVICE_PARAMS)
  770. )){
  771. err=GetLastError();
  772. goto RemoveDevice_Err;
  773. }
  774. if(!SetupDiCallClassInstaller(DIF_REMOVE,
  775. hDevInfo,
  776. &spDevInfoData
  777. )){
  778. err=GetLastError();
  779. goto RemoveDevice_Err;
  780. }
  781. //
  782. // Removal succeeded.
  783. //
  784. bStatus = TRUE;
  785. } // if(bIsInterfaceOnly)
  786. RemoveDevice_Err:
  787. if(IS_VALID_HANDLE(hDevInfo)){
  788. SetupDiDestroyDeviceInfoList(hDevInfo);
  789. }
  790. DebugTrace(TRACE_PROC_LEAVE,(("RemoveDevice... Ret=0x%x Err=0x%x.\r\n"), bStatus, err));
  791. return bStatus;
  792. } // RemoveDevice()
  793. DLLEXPORT
  794. VOID
  795. CALLBACK
  796. InstallWiaService(
  797. HWND hwnd,
  798. HINSTANCE hinst,
  799. LPTSTR lpszCmdLine,
  800. int nCmdShow
  801. )
  802. {
  803. DWORD dwError;
  804. DWORD dwStiCount;
  805. DWORD dwWiaCount;
  806. DebugTrace(TRACE_PROC_ENTER,(("InstallWiaService: Enter...\r\n")));
  807. //
  808. // Remove old service entry.
  809. //
  810. GetDeviceCount(&dwWiaCount, &dwStiCount);
  811. /* DEAD_CODE - Don't remove service!
  812. dwError = StiServiceRemove();
  813. if(NOERROR != dwError){
  814. DebugTrace(TRACE_ERROR,(("InstallWiaService: ERROR!! Unable to remove old service entry. Err=0x%x\n"), dwError));
  815. } // if(NOERROR != dwError)
  816. */
  817. //
  818. // Install WIA service. This will install only if the service failed to install during processing of STI.INF, else
  819. // it will simply change the StartType.
  820. //
  821. dwError = StiServiceInstall(TRUE,
  822. (0 == dwStiCount), // TRUE = on demand
  823. NULL,
  824. NULL);
  825. if(NOERROR != dwError){
  826. DebugTrace(TRACE_ERROR,(("InstallWiaService: ERROR!! Unable to install service. Err=0x%x\n"), dwError));
  827. } // if(NOERROR != dwError)
  828. //
  829. // Register WIA DLLs.
  830. //
  831. ExecCommandLine(TEXT("regsvr32.exe /s wiaservc.dll"));
  832. ExecCommandLine(TEXT("regsvr32.exe /s sti.dll"));
  833. ExecCommandLine(TEXT("regsvr32.exe /s wiascr.dll"));
  834. ExecCommandLine(TEXT("regsvr32.exe /s wiashext.dll"));
  835. ExecCommandLine(TEXT("regsvr32.exe /s camocx.dll"));
  836. ExecCommandLine(TEXT("regsvr32.exe /s wiadefui.dll"));
  837. ExecCommandLine(TEXT("wiaacmgr.exe /RegServer"));
  838. ExecCommandLine(TEXT("regsvr32.exe /s wiavusd.dll"));
  839. ExecCommandLine(TEXT("regsvr32.exe /s wiasf.ax"));
  840. ExecCommandLine(TEXT("rundll32.exe sti.dll,MigrateRegisteredSTIAppsForWIAEvents %%l"));
  841. DebugTrace(TRACE_PROC_LEAVE,(("InstallWiaService: Leaving... Ret=VOID.\r\n")));
  842. } // InstallWiaService()
  843. HANDLE
  844. SelectDevInfoFromFriendlyName(
  845. LPTSTR pszLocalName
  846. )
  847. {
  848. TCHAR szTemp[MAX_FRIENDLYNAME+1];
  849. HANDLE hDevInfo;
  850. GUID Guid;
  851. DWORD Idx;
  852. SP_DEVINFO_DATA spDevInfoData;
  853. BOOL bFound;
  854. HKEY hKeyDevice;
  855. ULONG cbData;
  856. LONG lResult;
  857. DebugTrace(TRACE_PROC_ENTER,(("SelectDevInfoFromFriendlyName: Enter...\r\n")));
  858. //
  859. // Initialize local.
  860. //
  861. hDevInfo = INVALID_HANDLE_VALUE;
  862. Guid = GUID_DEVCLASS_IMAGE;
  863. // Guid = KSCATEGORY_CAPTURE;
  864. Idx = 0;
  865. cbData = 0;
  866. bFound = FALSE;
  867. hKeyDevice = NULL;
  868. lResult = ERROR_SUCCESS;
  869. memset(szTemp, 0, sizeof(szTemp));
  870. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  871. //
  872. // Check argument.
  873. //
  874. if(NULL == pszLocalName){
  875. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromFriendlyName: Invalid arbument.\r\n")));
  876. hDevInfo = INVALID_HANDLE_VALUE;
  877. goto SelectDevInfoFromFriendlyName_return;
  878. }
  879. //
  880. // Get device info set of specified class.
  881. //
  882. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE);
  883. if (hDevInfo == INVALID_HANDLE_VALUE) {
  884. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromFriendlyName: SetupDiGetClassDevs failed. Err=0x%x\r\n"), GetLastError()));
  885. hDevInfo = INVALID_HANDLE_VALUE;
  886. goto SelectDevInfoFromFriendlyName_return;
  887. }
  888. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  889. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  890. DebugTrace(TRACE_STATUS,(("SelectDevInfoFromFriendlyName: Checking Device(0x%x)\r\n"), Idx));
  891. hKeyDevice = SetupDiOpenDevRegKey (hDevInfo,
  892. &spDevInfoData,
  893. DICS_FLAG_GLOBAL,
  894. 0,
  895. DIREG_DRV,
  896. KEY_READ);
  897. if (hKeyDevice != INVALID_HANDLE_VALUE) {
  898. //
  899. // Is FriendlyName == pszLocalName?
  900. //
  901. cbData = sizeof(szTemp);
  902. lResult = RegQueryValueEx(hKeyDevice,
  903. REGSTR_VAL_FRIENDLY_NAME,
  904. NULL,
  905. NULL,
  906. (LPBYTE)szTemp,
  907. &cbData);
  908. if(ERROR_SUCCESS == lResult){
  909. if(_tcsicmp((LPCTSTR)pszLocalName, (LPCTSTR)szTemp) != 0) {
  910. //
  911. // Doesn't match, skip this one.
  912. //
  913. RegCloseKey(hKeyDevice);
  914. continue;
  915. }
  916. } else {
  917. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromFriendlyName: can't get FriendlyName. Err=0x%x\r\n"), GetLastError()));
  918. RegCloseKey(hKeyDevice);
  919. continue;
  920. }
  921. //
  922. // Found the target!
  923. //
  924. bFound = TRUE;
  925. RegCloseKey(hKeyDevice);
  926. break;
  927. } else {
  928. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromFriendlyName: Invalid handle.\r\n"), GetLastError()));
  929. } // if (hKeyDevice != INVALID_HANDLE_VALUE)
  930. } //for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  931. SelectDevInfoFromFriendlyName_return:
  932. if(!bFound){
  933. //
  934. // FriendleName is not found.
  935. //
  936. if (IS_VALID_HANDLE(hDevInfo)) {
  937. SetupDiDestroyDeviceInfoList(hDevInfo);
  938. hDevInfo = INVALID_HANDLE_VALUE;
  939. }
  940. } else {
  941. //
  942. // Device found. Select found device.
  943. //
  944. SetupDiSetSelectedDevice(hDevInfo, &spDevInfoData);
  945. }
  946. DebugTrace(TRACE_PROC_LEAVE,(("SelectDevInfoFromFriendlyName: Leaving... Ret=0x%x\r\n"), hDevInfo));
  947. return hDevInfo;
  948. } // SelectDevInfoFromFriendlyName()
  949. HANDLE
  950. SelectDevInfoFromDeviceId(
  951. LPTSTR pszDeviceId
  952. )
  953. {
  954. TCHAR szTemp[MAX_DEVICE_ID];
  955. HANDLE hDevInfo;
  956. GUID Guid;
  957. DWORD Idx;
  958. SP_DEVINFO_DATA spDevInfoData;
  959. BOOL bFound;
  960. HKEY hKeyDevice;
  961. ULONG cbData;
  962. LONG lResult;
  963. DebugTrace(TRACE_PROC_ENTER,(("SelectDevInfoFromDeviceId: Enter...\r\n")));
  964. //
  965. // Initialize local.
  966. //
  967. hDevInfo = INVALID_HANDLE_VALUE;
  968. Guid = GUID_DEVCLASS_IMAGE;
  969. // Guid = KSCATEGORY_CAPTURE;
  970. Idx = 0;
  971. cbData = 0;
  972. bFound = FALSE;
  973. hKeyDevice = NULL;
  974. lResult = ERROR_SUCCESS;
  975. memset(szTemp, 0, sizeof(szTemp));
  976. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  977. //
  978. // Check argument.
  979. //
  980. if(NULL == pszDeviceId){
  981. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromDeviceId: Invalid arbument.\r\n")));
  982. hDevInfo = INVALID_HANDLE_VALUE;
  983. goto SelectDevInfoFromDeviceId_return;
  984. }
  985. //
  986. // Get device info set of specified class.
  987. //
  988. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE);
  989. if (hDevInfo == INVALID_HANDLE_VALUE) {
  990. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromDeviceId: SetupDiGetClassDevs failed. Err=0x%x\r\n"), GetLastError()));
  991. hDevInfo = INVALID_HANDLE_VALUE;
  992. goto SelectDevInfoFromDeviceId_return;
  993. }
  994. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  995. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  996. DebugTrace(TRACE_STATUS,(("SelectDevInfoFromDeviceId: Checking Device(0x%x)\r\n"), Idx));
  997. hKeyDevice = SetupDiOpenDevRegKey (hDevInfo,
  998. &spDevInfoData,
  999. DICS_FLAG_GLOBAL,
  1000. 0,
  1001. DIREG_DRV,
  1002. KEY_READ);
  1003. if (hKeyDevice != INVALID_HANDLE_VALUE) {
  1004. //
  1005. // Is DeviceId == pszDeviceId?
  1006. //
  1007. cbData = sizeof(szTemp);
  1008. lResult = RegQueryValueEx(hKeyDevice,
  1009. REGSTR_VAL_DEVICE_ID,
  1010. NULL,
  1011. NULL,
  1012. (LPBYTE)szTemp,
  1013. &cbData);
  1014. if(ERROR_SUCCESS == lResult){
  1015. if(_tcsicmp((LPCTSTR)pszDeviceId, (LPCTSTR)szTemp) != 0) {
  1016. //
  1017. // Doesn't match, skip this one.
  1018. //
  1019. RegCloseKey(hKeyDevice);
  1020. continue;
  1021. }
  1022. } else {
  1023. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromDeviceId: can't get DeviceId. Err=0x%x\r\n"), GetLastError()));
  1024. RegCloseKey(hKeyDevice);
  1025. continue;
  1026. }
  1027. //
  1028. // Found the target!
  1029. //
  1030. bFound = TRUE;
  1031. RegCloseKey(hKeyDevice);
  1032. break;
  1033. } else {
  1034. DebugTrace(TRACE_ERROR,(("SelectDevInfoFromDeviceId: Invalid handle.\r\n"), GetLastError()));
  1035. } // if (hKeyDevice != INVALID_HANDLE_VALUE)
  1036. } //for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  1037. SelectDevInfoFromDeviceId_return:
  1038. if(!bFound){
  1039. //
  1040. // FriendleName is not found.
  1041. //
  1042. if (IS_VALID_HANDLE(hDevInfo)) {
  1043. SetupDiDestroyDeviceInfoList(hDevInfo);
  1044. hDevInfo = INVALID_HANDLE_VALUE;
  1045. }
  1046. } else {
  1047. //
  1048. // Device found. Select found device.
  1049. //
  1050. SetupDiSetSelectedDevice(hDevInfo, &spDevInfoData);
  1051. }
  1052. DebugTrace(TRACE_PROC_LEAVE,(("SelectDevInfoFromDeviceId: Leaving... Ret=0x%x\r\n"), hDevInfo));
  1053. return hDevInfo;
  1054. } // SelectDevInfoFromDeviceId()
  1055. HANDLE
  1056. GetDeviceInterfaceIndex(
  1057. LPTSTR pszDeviceId,
  1058. DWORD *pdwIndex
  1059. )
  1060. {
  1061. TCHAR szTemp[MAX_DEVICE_ID];
  1062. HANDLE hDevInfo;
  1063. GUID Guid;
  1064. DWORD Idx;
  1065. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  1066. BOOL bFound;
  1067. HKEY hKeyInterface;
  1068. ULONG cbData;
  1069. LONG lResult;
  1070. DebugTrace(TRACE_PROC_ENTER,(("GetDeviceInterfaceIndex: Enter... DeviceId=%ws\r\n"), pszDeviceId));
  1071. //
  1072. // Initialize local.
  1073. //
  1074. hDevInfo = INVALID_HANDLE_VALUE;
  1075. Guid = GUID_DEVCLASS_IMAGE;
  1076. Idx = 0;
  1077. cbData = 0;
  1078. bFound = FALSE;
  1079. hKeyInterface = NULL;
  1080. lResult = ERROR_SUCCESS;
  1081. memset(szTemp, 0, sizeof(szTemp));
  1082. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  1083. //
  1084. // Check argument.
  1085. //
  1086. if(NULL == pszDeviceId){
  1087. DebugTrace(TRACE_ERROR,(("GetDeviceInterfaceIndex: Invalid arbument.\r\n")));
  1088. hDevInfo = INVALID_HANDLE_VALUE;
  1089. goto GetDeviceInterfaceIndex_return;
  1090. }
  1091. //
  1092. // Get device info set of specified class interface.
  1093. //
  1094. hDevInfo = SetupDiGetClassDevs (&Guid,
  1095. NULL,
  1096. NULL,
  1097. DIGCF_DEVICEINTERFACE | DIGCF_PROFILE);
  1098. if (hDevInfo == INVALID_HANDLE_VALUE) {
  1099. DebugTrace(TRACE_ERROR,(("GetDeviceInterfaceIndex: SetupDiGetClassDevs failed. Err=0x%x\r\n"), GetLastError()));
  1100. hDevInfo = INVALID_HANDLE_VALUE;
  1101. goto GetDeviceInterfaceIndex_return;
  1102. }
  1103. spDevInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
  1104. for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) {
  1105. DebugTrace(TRACE_STATUS,(("GetDeviceInterfaceIndex: Checking Interface(0x%x)\r\n"), Idx));
  1106. hKeyInterface = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  1107. &spDevInterfaceData,
  1108. 0,
  1109. KEY_ALL_ACCESS);
  1110. if (INVALID_HANDLE_VALUE != hKeyInterface) {
  1111. //
  1112. // Is FriendlyName == pszLocalName?
  1113. //
  1114. cbData = sizeof(szTemp);
  1115. lResult = RegQueryValueEx(hKeyInterface,
  1116. REGSTR_VAL_DEVICE_ID,
  1117. NULL,
  1118. NULL,
  1119. (LPBYTE)szTemp,
  1120. &cbData);
  1121. if(ERROR_SUCCESS == lResult){
  1122. if(_tcsicmp((LPCTSTR)pszDeviceId, (LPCTSTR)szTemp) == 0) {
  1123. //
  1124. // Found the target!
  1125. //
  1126. bFound = TRUE;
  1127. RegCloseKey(hKeyInterface);
  1128. break;
  1129. }
  1130. } else { // if(ERROR_SUCCESS == lResult)
  1131. DebugTrace(TRACE_STATUS,(("GetDeviceInterfaceIndex: can't get DeviceID. Err=0x%x\r\n"), GetLastError()));
  1132. } // if(ERROR_SUCCESS == lResult)
  1133. RegCloseKey(hKeyInterface);
  1134. hKeyInterface = NULL;
  1135. } else { // if (hKeyDevice != INVALID_HANDLE_VALUE)
  1136. DWORD Err;
  1137. Err = GetLastError();
  1138. DebugTrace(TRACE_ERROR,(("GetDeviceInterfaceIndex: Invalid handle. Err=0x%x.\r\n"), Err));
  1139. } // if (hKeyDevice != INVALID_HANDLE_VALUE)
  1140. } //for (Idx = 0; SetupDiEnumDeviceInterface (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++)
  1141. GetDeviceInterfaceIndex_return:
  1142. if(FALSE == bFound){
  1143. if (IS_VALID_HANDLE(hDevInfo)) {
  1144. SetupDiDestroyDeviceInfoList(hDevInfo);
  1145. hDevInfo = INVALID_HANDLE_VALUE;
  1146. }
  1147. *pdwIndex = INVALID_DEVICE_INDEX;
  1148. } else {
  1149. //
  1150. // Interface found.
  1151. //
  1152. *pdwIndex = Idx;
  1153. }
  1154. DebugTrace(TRACE_PROC_LEAVE,(("GetDeviceInterfaceIndex: Leaving... Ret=0x%x\r\n"), hDevInfo));
  1155. return hDevInfo;
  1156. } // GetDeviceInterfaceIndex()
  1157. INT CALLBACK
  1158. iHdwWizardDlgCallback(
  1159. IN HWND hwndDlg,
  1160. IN UINT uMsg,
  1161. IN LPARAM lParam
  1162. )
  1163. /*++
  1164. Routine Description:
  1165. Call back used to remove the "?" from the wizard page.
  1166. Arguments:
  1167. hwndDlg - Handle to the property sheet dialog box.
  1168. uMsg - Identifies the message being received. This parameter
  1169. is one of the following values:
  1170. PSCB_INITIALIZED - Indicates that the property sheet is
  1171. being initialized. The lParam value is zero for this message.
  1172. PSCB_PRECREATE Indicates that the property sheet is about
  1173. to be created. The hwndDlg parameter is NULL and the lParam
  1174. parameter is a pointer to a dialog template in memory. This
  1175. template is in the form of a DLGTEMPLATE structure followed
  1176. by one or more DLGITEMTEMPLATE structures.
  1177. lParam - Specifies additional information about the message. The
  1178. meaning of this value depends on the uMsg parameter.
  1179. Return Value:
  1180. The function returns zero.
  1181. --*/
  1182. {
  1183. switch( uMsg ) {
  1184. case PSCB_INITIALIZED:
  1185. break;
  1186. case PSCB_PRECREATE:
  1187. if( lParam ){
  1188. DLGTEMPLATE *pDlgTemplate = (DLGTEMPLATE *)lParam;
  1189. pDlgTemplate->style &= ~DS_CONTEXTHELP;
  1190. }
  1191. break;
  1192. }
  1193. return FALSE;
  1194. }
  1195. BOOL
  1196. SetSelectDevTitleAndInstructions(
  1197. HDEVINFO hDevInfo,
  1198. PSP_DEVINFO_DATA pspDevInfoData,
  1199. LPCTSTR pszTitle,
  1200. LPCTSTR pszSubTitle,
  1201. LPCTSTR pszInstn,
  1202. LPCTSTR pszListLabel
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. Arguments:
  1207. Return Value:
  1208. Side effects:
  1209. --*/
  1210. {
  1211. SP_SELECTDEVICE_PARAMS SelectDevParams;
  1212. BOOL fRet;
  1213. memset((void *)&SelectDevParams, 0, sizeof(SelectDevParams));
  1214. if ( pszTitle && (lstrlen(pszTitle) + 1 > MAX_TITLE_LEN ) ) {
  1215. SetLastError(ERROR_INVALID_PARAMETER);
  1216. return FALSE;
  1217. }
  1218. if ( pszSubTitle && (lstrlen(pszSubTitle) + 1 > MAX_SUBTITLE_LEN )) {
  1219. SetLastError(ERROR_INVALID_PARAMETER);
  1220. return FALSE;
  1221. }
  1222. if ( pszInstn && (lstrlen(pszInstn) + 1 > MAX_INSTRUCTION_LEN )) {
  1223. SetLastError(ERROR_INVALID_PARAMETER);
  1224. return FALSE;
  1225. }
  1226. if ( pszListLabel && (lstrlen(pszListLabel) + 1 > MAX_LABEL_LEN )) {
  1227. SetLastError(ERROR_INVALID_PARAMETER);
  1228. return FALSE;
  1229. }
  1230. SelectDevParams.ClassInstallHeader.cbSize
  1231. = sizeof(SelectDevParams.ClassInstallHeader);
  1232. if ( !SetupDiGetClassInstallParams(hDevInfo,
  1233. pspDevInfoData,
  1234. &SelectDevParams.ClassInstallHeader,
  1235. sizeof(SelectDevParams),
  1236. NULL) ) {
  1237. DWORD dwErr = GetLastError();
  1238. if (ERROR_NO_CLASSINSTALL_PARAMS != dwErr ) {
  1239. return FALSE;
  1240. }
  1241. }
  1242. if ( pszTitle )
  1243. lstrcpy(SelectDevParams.Title, pszTitle);
  1244. if ( pszSubTitle )
  1245. lstrcpy(SelectDevParams.SubTitle, pszSubTitle);
  1246. if ( pszInstn )
  1247. lstrcpy(SelectDevParams.Instructions, pszInstn);
  1248. if ( pszListLabel )
  1249. lstrcpy(SelectDevParams.ListLabel, pszListLabel);
  1250. SelectDevParams.ClassInstallHeader.InstallFunction = DIF_SELECTDEVICE;
  1251. fRet = SetupDiSetClassInstallParams(hDevInfo,
  1252. pspDevInfoData,
  1253. &SelectDevParams.ClassInstallHeader,
  1254. sizeof(SelectDevParams));
  1255. return fRet;
  1256. }
  1257. DLLEXPORT
  1258. BOOL
  1259. WINAPI
  1260. WiaDeviceEnum(
  1261. VOID
  1262. )
  1263. {
  1264. BOOL rVal = FALSE;
  1265. SC_HANDLE hSvcMgr = NULL;
  1266. SC_HANDLE hService = NULL;
  1267. SERVICE_STATUS ServiceStatus;
  1268. UINT uiRetry = 10;
  1269. DebugTrace(TRACE_PROC_ENTER,(("WiaDeviceEnum: Enter... \r\n")));
  1270. //
  1271. // Open Service Control Manager.
  1272. //
  1273. hSvcMgr = OpenSCManager(
  1274. NULL,
  1275. NULL,
  1276. SC_MANAGER_ALL_ACCESS
  1277. );
  1278. if (!hSvcMgr) {
  1279. DebugTrace(TRACE_ERROR,(("WiaDeviceEnum: ERROR!! OpenSCManager failed. Err=0x%x\n"), GetLastError()));
  1280. goto exit;
  1281. }
  1282. //
  1283. // Open WIA service.
  1284. //
  1285. hService = OpenService(
  1286. hSvcMgr,
  1287. STI_SERVICE_NAME,
  1288. SERVICE_ALL_ACCESS
  1289. );
  1290. if (!hService) {
  1291. DebugTrace(TRACE_ERROR,(("WiaDeviceEnum: ERROR!! OpenService failed. Err=0x%x\n"), GetLastError()));
  1292. goto exit;
  1293. }
  1294. //
  1295. // Inform WIA service to refresh its device list.
  1296. //
  1297. rVal = ControlService(hService,
  1298. STI_SERVICE_CONTROL_REFRESH,
  1299. &ServiceStatus);
  1300. if (!rVal) {
  1301. DebugTrace(TRACE_ERROR,(("WiaDeviceEnum: ERROR!! ControlService failed. Err=0x%x\n"), GetLastError()));
  1302. goto exit;
  1303. }
  1304. exit:
  1305. if(NULL != hService){
  1306. CloseServiceHandle( hService );
  1307. }
  1308. if(NULL != hSvcMgr){
  1309. CloseServiceHandle( hSvcMgr );
  1310. }
  1311. DebugTrace(TRACE_PROC_LEAVE,(("WiaDeviceEnum: Leaving... Ret=0x%x\n"), rVal));
  1312. return rVal;
  1313. } // WiaDeviceEnum()
  1314. DLLEXPORT
  1315. PWIA_PORTLIST
  1316. WINAPI
  1317. WiaCreatePortList(
  1318. LPWSTR szDeviceId
  1319. )
  1320. {
  1321. PWIA_PORTLIST pReturn;
  1322. GUID PortGuid;
  1323. HDEVINFO hPortDevInfo = NULL;
  1324. DWORD Idx;
  1325. DWORD dwRequired;
  1326. DWORD dwNumberOfPorts;
  1327. DWORD dwSize;
  1328. CStringArray csaPortName;
  1329. TCHAR szPortName[MAX_DESCRIPTION];
  1330. TCHAR szPortFriendlyName[MAX_DESCRIPTION];
  1331. BOOL bIsSerial;
  1332. BOOL bIsParallel;
  1333. BOOL bIsAutoCapable;
  1334. BOOL bIsPortSelectable;
  1335. //
  1336. // Initialize local.
  1337. //
  1338. Idx = 0;
  1339. hPortDevInfo = NULL;
  1340. pReturn = NULL;
  1341. dwSize = 0;
  1342. dwRequired = 0;
  1343. dwNumberOfPorts = 0;
  1344. bIsSerial = TRUE;
  1345. bIsParallel = TRUE;
  1346. bIsAutoCapable = FALSE;
  1347. bIsPortSelectable = TRUE;
  1348. memset(szPortName, 0, sizeof(szPortName));
  1349. memset(szPortFriendlyName, 0, sizeof(szPortFriendlyName));
  1350. //
  1351. // Convert from WCHAR to TCHAR
  1352. //
  1353. #ifndef UNICODE
  1354. #pragma message("Not optimal conversion - reimplement if running on nonUNICODE system")
  1355. TCHAR szDeviceIdConverted[STI_MAX_INTERNAL_NAME_LENGTH+1];
  1356. szDeviceIdConverted[0] = TEXT('\0');
  1357. MultiByteToWideChar(CP_ACP,
  1358. 0,
  1359. szDeviceIdConverted, -1,
  1360. szDeviceId, sizeof(szDeviceId));
  1361. #else
  1362. // On UNICODE system use the same buffer
  1363. #define szDeviceIdConverted szDeviceId
  1364. #endif
  1365. if(!CheckPortForDevice(szDeviceIdConverted, &bIsSerial, &bIsParallel, &bIsAutoCapable, &bIsPortSelectable)){
  1366. DebugTrace(TRACE_ERROR,(("WiaGetPortList: ERROR!! Unable to get port info for device.\r\n")));
  1367. pReturn = NULL;
  1368. goto WiaGetPortList_return;
  1369. }
  1370. if(bIsAutoCapable){
  1371. dwNumberOfPorts++;
  1372. csaPortName.Add(AUTO);
  1373. }
  1374. //
  1375. // Enumerate all Port class devices if "PortSelect=NO" is not specified.
  1376. //
  1377. if(bIsPortSelectable){
  1378. //
  1379. // Get GUID of port device.
  1380. //
  1381. if(!SetupDiClassGuidsFromName (PORTS, &PortGuid, sizeof(GUID), &dwRequired)){
  1382. DebugTrace(TRACE_ERROR,(("WiaGetPortList: ERROR!! SetupDiClassGuidsFromName Failed. Err=0x%lX\r\n"), GetLastError()));
  1383. pReturn = NULL;
  1384. goto WiaGetPortList_return;
  1385. } // if(!SetupDiClassGuidsFromName (PORTS, &Guid, sizeof(GUID), &dwRequired))
  1386. //
  1387. // Get device info set of port devices.
  1388. //
  1389. hPortDevInfo = SetupDiGetClassDevs (&PortGuid,
  1390. NULL,
  1391. NULL,
  1392. DIGCF_PRESENT | DIGCF_PROFILE);
  1393. if (hPortDevInfo == INVALID_HANDLE_VALUE) {
  1394. DebugTrace(TRACE_ERROR,(("WiaGetPortList: ERROR!! SetupDiGetClassDevs Failed. Err=0x%lX\r\n"), GetLastError()));
  1395. pReturn = NULL;
  1396. goto WiaGetPortList_return;
  1397. }
  1398. //
  1399. // Process all of device element listed in device info set.
  1400. //
  1401. for(Idx = 0; GetPortNamesFromIndex(hPortDevInfo, Idx, szPortName, szPortFriendlyName); Idx++){
  1402. //
  1403. // Add valid Port CreateFile/Friendly Name to array.
  1404. //
  1405. if(0 == lstrlen(szPortName)){
  1406. DebugTrace(TRACE_ERROR,(("WiaGetPortList: ERROR!! Invalid Port/Friendly Name.\r\n")));
  1407. szPortName[0] = TEXT('\0');
  1408. continue;
  1409. }
  1410. DebugTrace(TRACE_STATUS,(("WiaGetPortList: Found Port %d: %ws.\r\n"), Idx, szPortName));
  1411. //
  1412. // Check it's port type.
  1413. //
  1414. if(_tcsstr((const TCHAR *)szPortName, TEXT("LPT"))){
  1415. if(!bIsParallel){
  1416. szPortName[0] = TEXT('\0');
  1417. continue;
  1418. }
  1419. }
  1420. if(_tcsstr((const TCHAR *)szPortName, TEXT("COM"))){
  1421. if(!bIsSerial){
  1422. szPortName[0] = TEXT('\0');
  1423. continue;
  1424. }
  1425. }
  1426. dwNumberOfPorts++;
  1427. csaPortName.Add(szPortName);
  1428. szPortName[0] = TEXT('\0');
  1429. } // for(Idx = 0; GetPortNamesFromIndex(hPortDevInfo, Idx, szPortName, szPortFriendlyName); Idx++)
  1430. } // if(bIsPortSelectable)
  1431. if(0 != dwNumberOfPorts){
  1432. //
  1433. // Allocate memory for returning structure.
  1434. //
  1435. dwSize = sizeof(DWORD) + sizeof(LPTSTR)*dwNumberOfPorts;
  1436. pReturn = (PWIA_PORTLIST)new BYTE[dwSize];
  1437. if(NULL == pReturn){
  1438. goto WiaGetPortList_return;
  1439. }
  1440. memset(pReturn, 0, dwSize);
  1441. //
  1442. // Fill in the info.
  1443. //
  1444. pReturn->dwNumberOfPorts = dwNumberOfPorts;
  1445. for(Idx = 0; Idx < dwNumberOfPorts; Idx++){
  1446. pReturn->szPortName[Idx] = (LPTSTR)new BYTE[lstrlen(csaPortName[Idx])*sizeof(TCHAR)+sizeof(TEXT('\0'))];
  1447. if(NULL != pReturn->szPortName[Idx]){
  1448. lstrcpy(pReturn->szPortName[Idx], csaPortName[Idx]);
  1449. } else {
  1450. WiaDestroyPortList(pReturn);
  1451. pReturn = NULL;
  1452. break;
  1453. } // if(NULL != pReturn->szPortName[Idx])
  1454. } // for(Idx = 0; Idx < dwNumberOfPorts; Idx++)
  1455. } // if(0 != dwNumberOfPorts)
  1456. WiaGetPortList_return:
  1457. //
  1458. // Cleanup
  1459. //
  1460. if ( IS_VALID_HANDLE(hPortDevInfo) ) {
  1461. SetupDiDestroyDeviceInfoList(hPortDevInfo);
  1462. }
  1463. return pReturn;
  1464. } // WiaCreatePortList()
  1465. DLLEXPORT
  1466. VOID
  1467. WINAPI
  1468. WiaDestroyPortList(
  1469. PWIA_PORTLIST pWiaPortList
  1470. )
  1471. {
  1472. DWORD Idx;
  1473. if(NULL == pWiaPortList){
  1474. return;
  1475. } // if(NULL == pWiaPortList)
  1476. for(Idx = 0; Idx < pWiaPortList->dwNumberOfPorts; Idx++){
  1477. if(NULL != pWiaPortList->szPortName[Idx]){
  1478. delete pWiaPortList->szPortName[Idx];
  1479. } // if(NULL != pWiaPortList->szPortName[Idx])
  1480. } // for(Idx = 0; Idx < pWiaPortList; Idx++)
  1481. delete pWiaPortList;
  1482. return;
  1483. } // WiaDestroyPortList()
  1484. BOOL
  1485. CheckPortForDevice(
  1486. LPTSTR szDeviceId,
  1487. BOOL *pbIsSerial,
  1488. BOOL *pbIsParallel,
  1489. BOOL *pbIsAutoCapable,
  1490. BOOL *pbIsPortSelectable
  1491. )
  1492. {
  1493. GUID WiaGuid;
  1494. HDEVINFO hWiaDevInfo;
  1495. DWORD dwCapability;
  1496. SP_DEVINFO_DATA spDevInfoData;
  1497. CString csConnection;
  1498. CString csPortSelect;
  1499. DWORD dwDeviceIndex;
  1500. HKEY hkDevice;
  1501. BOOL bCapabilityAcquired;
  1502. BOOL bRet;
  1503. BOOL bIsSerial;
  1504. BOOL bIsParallel;
  1505. BOOL bIsAutoCapable;
  1506. BOOL bIsPortSelectable;
  1507. DWORD dwIsPnp;
  1508. //
  1509. // Initialize locals.
  1510. //
  1511. dwCapability = 0;
  1512. dwIsPnp = 0;
  1513. hWiaDevInfo = INVALID_HANDLE_VALUE;
  1514. dwDeviceIndex = INVALID_DEVICE_INDEX;
  1515. WiaGuid = GUID_DEVCLASS_IMAGE;
  1516. bRet = FALSE;
  1517. bCapabilityAcquired = FALSE;
  1518. bIsSerial = TRUE;
  1519. bIsParallel = TRUE;
  1520. bIsAutoCapable = FALSE;
  1521. bIsPortSelectable = TRUE;
  1522. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  1523. //
  1524. // Get specified device property.
  1525. //
  1526. hWiaDevInfo = SelectDevInfoFromDeviceId(szDeviceId);
  1527. if(INVALID_HANDLE_VALUE != hWiaDevInfo){
  1528. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  1529. SetupDiGetSelectedDevice(hWiaDevInfo, &spDevInfoData);
  1530. hkDevice = SetupDiOpenDevRegKey(hWiaDevInfo,
  1531. &spDevInfoData,
  1532. DICS_FLAG_GLOBAL,
  1533. 0,
  1534. DIREG_DRV,
  1535. KEY_READ);
  1536. if(INVALID_HANDLE_VALUE != hkDevice){
  1537. csConnection.Load(hkDevice, CONNECTION);
  1538. csPortSelect.Load(hkDevice, PORTSELECT);
  1539. GetDwordFromRegistry(hkDevice, ISPNP, &dwIsPnp);
  1540. if(GetDwordFromRegistry(hkDevice, CAPABILITIES, &dwCapability)){
  1541. bCapabilityAcquired = TRUE;
  1542. } // if(GetDwordFromRegistry(hkDevice, CAPABILITIES, &dwCapability))
  1543. RegCloseKey(hkDevice);
  1544. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  1545. } // if(INVALID_HANDLE_VALUE != hkDevice)
  1546. SetupDiDestroyDeviceInfoList(hWiaDevInfo);
  1547. hWiaDevInfo = INVALID_HANDLE_VALUE;
  1548. } else { // if(INVALID_HANDLE_VALUE != hDevInfo)
  1549. SP_DEVICE_INTERFACE_DATA spDeviceInterfaceData;
  1550. //
  1551. // See if it's "Interface-only" device.
  1552. //
  1553. hWiaDevInfo = GetDeviceInterfaceIndex(szDeviceId, &dwDeviceIndex);
  1554. if( (INVALID_HANDLE_VALUE == hWiaDevInfo)
  1555. || (INVALID_DEVICE_INDEX == dwDeviceIndex) )
  1556. {
  1557. DebugTrace(TRACE_ERROR,(("CheckPortForDevice: ERROR!! Can't find \"%ws\".\r\n"), szDeviceId));
  1558. bRet = FALSE;
  1559. goto CheckPortForDevice_return;
  1560. }
  1561. spDeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  1562. if(!SetupDiEnumDeviceInterfaces(hWiaDevInfo, NULL, &WiaGuid, dwDeviceIndex, &spDeviceInterfaceData)){
  1563. DebugTrace(TRACE_ERROR,(("CheckPortForDevice: ERROR!! SetupDiEnumDeviceInterfaces() failed. Err=0x%x.\r\n"), GetLastError()));
  1564. bRet = FALSE;
  1565. goto CheckPortForDevice_return;
  1566. }
  1567. hkDevice = SetupDiOpenDeviceInterfaceRegKey(hWiaDevInfo, &spDeviceInterfaceData, 0, KEY_READ);
  1568. if(INVALID_HANDLE_VALUE == hkDevice){
  1569. DebugTrace(TRACE_ERROR,(("CheckPortForDevice: ERROR!! SetupDiOpenDeviceInterfaceRegKey() failed. Err=0x%x.\r\n"), GetLastError()));
  1570. bRet = FALSE;
  1571. goto CheckPortForDevice_return;
  1572. }
  1573. csConnection.Load(hkDevice, CONNECTION);
  1574. csPortSelect.Load(hkDevice, PORTSELECT);
  1575. GetDwordFromRegistry(hkDevice, ISPNP, &dwIsPnp);
  1576. if(GetDwordFromRegistry(hkDevice, CAPABILITIES, &dwCapability)){
  1577. bCapabilityAcquired = TRUE;
  1578. } // if(GetDwordFromRegistry(hkDevice, CAPABILITIES, &dwCapability))
  1579. RegCloseKey(hkDevice);
  1580. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  1581. } // else (INVALID_HANDLE_VALUE != hDevInfo)
  1582. //
  1583. // Check what port should be shown.
  1584. //
  1585. if(0 != dwIsPnp){
  1586. //
  1587. // This is PnP device. No port should be available.
  1588. //
  1589. bRet = FALSE;
  1590. goto CheckPortForDevice_return;
  1591. }
  1592. if(bCapabilityAcquired){
  1593. if(csConnection.IsEmpty()){
  1594. bIsSerial = TRUE;
  1595. bIsParallel = TRUE;
  1596. } else {
  1597. if(0 == _tcsicmp((LPTSTR)csConnection, SERIAL)){
  1598. bIsSerial = TRUE;
  1599. bIsParallel = FALSE;
  1600. }
  1601. if(0 == _tcsicmp((LPTSTR)csConnection, PARALLEL)){
  1602. bIsSerial = FALSE;
  1603. bIsParallel = TRUE;
  1604. }
  1605. }
  1606. if(dwCapability & STI_GENCAP_AUTO_PORTSELECT){
  1607. bIsAutoCapable = TRUE;
  1608. } else {
  1609. bIsAutoCapable = FALSE;
  1610. }
  1611. if(0 == lstrcmpi((LPTSTR)csPortSelect, NO)){
  1612. bIsPortSelectable = FALSE;
  1613. } else {// if(0 == lstrcmpi(csPortSelect, NO))
  1614. bIsPortSelectable = TRUE;
  1615. }
  1616. } else {
  1617. DebugTrace(TRACE_ERROR,(("CheckPortForDevice: ERROR!! Unable to acquire info from registry.\r\n")));
  1618. bRet = FALSE;
  1619. goto CheckPortForDevice_return;
  1620. }
  1621. //
  1622. // Operation succeeded.
  1623. //
  1624. bRet = TRUE;
  1625. CheckPortForDevice_return:
  1626. if(IS_VALID_HANDLE(hWiaDevInfo)){
  1627. SetupDiDestroyDeviceInfoList(hWiaDevInfo);
  1628. }
  1629. if(bRet){
  1630. *pbIsSerial = bIsSerial;
  1631. *pbIsParallel = bIsParallel;
  1632. *pbIsAutoCapable = bIsAutoCapable;
  1633. *pbIsPortSelectable = bIsPortSelectable;
  1634. }
  1635. return bRet;
  1636. } // CheckPortForDevice()
  1637. DLLEXPORT
  1638. BOOL
  1639. WINAPI
  1640. MigrateDevice(
  1641. PDEVICE_INFO pMigratingDevice
  1642. )
  1643. {
  1644. BOOL bSucceeded;
  1645. //
  1646. // Initialize local.
  1647. //
  1648. bSucceeded = TRUE;
  1649. //
  1650. // Create Device class object.
  1651. //
  1652. CDevice cdThis(pMigratingDevice);
  1653. //
  1654. // Set default devnode selector.
  1655. //
  1656. cdThis.SetDevnodeSelectCallback((DEVNODESELCALLBACK)GetDevinfoFromPortName);
  1657. //
  1658. // Generate FriendlyName.
  1659. //
  1660. cdThis.NameDefaultUniqueName();
  1661. //
  1662. // Install(migrate) the device.
  1663. //
  1664. bSucceeded = cdThis.PreInstall();
  1665. if(bSucceeded){
  1666. bSucceeded = cdThis.Install();
  1667. }
  1668. //
  1669. // Do final touch. Clean up if failed, or finish installation.
  1670. //
  1671. cdThis.PostInstall(bSucceeded);
  1672. return bSucceeded;
  1673. } // MigrateDevice()