Leaked source code of windows server 2003
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.

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