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.

1122 lines
37 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: Entry.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: KeisukeT
  10. *
  11. * DATE: 27 Mar, 2000
  12. *
  13. * DESCRIPTION:
  14. * Co/Installer/DLL entry point.
  15. *
  16. *******************************************************************************/
  17. //
  18. // Precompiled header
  19. //
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. //
  23. // Include
  24. //
  25. #include "sti_ci.h"
  26. #include <setupapi.h>
  27. #include "firstpg.h"
  28. #include "portsel.h"
  29. #include "nameit.h"
  30. #include "finalpg.h"
  31. #include "prevpg.h"
  32. #include "device.h"
  33. #include "stiregi.h"
  34. #include "userdbg.h"
  35. //
  36. // Global
  37. //
  38. HINSTANCE g_hDllInstance = NULL;
  39. //
  40. // Function
  41. //
  42. extern "C"
  43. BOOL
  44. APIENTRY
  45. DllMain(
  46. IN HINSTANCE hDll,
  47. IN ULONG ulReason,
  48. IN LPVOID lpReserved
  49. )
  50. /*++
  51. Routine Description:
  52. DllMain
  53. Entrypoint when this DLL is loaded.
  54. Arguments:
  55. IN HINSTANCE hDll Handle to this DLL instance.
  56. IN ULONG ulReason The reason this entry is called.
  57. IN LPVOID lpReserved
  58. Return Value:
  59. TRUE always.
  60. Side effects:
  61. None
  62. --*/
  63. {
  64. if (ulReason == DLL_PROCESS_ATTACH) {
  65. //
  66. // Initialize globals.
  67. //
  68. g_hDllInstance = hDll;
  69. //
  70. // Initialize Fusion
  71. //
  72. SHFusionInitializeFromModuleID( hDll, 123 );
  73. DisableThreadLibraryCalls(hDll);
  74. InitCommonControls();
  75. DBG_INIT(g_hDllInstance);
  76. // MyDebugInit();
  77. }
  78. else if (ulReason == DLL_PROCESS_DETACH) {
  79. //
  80. // Shutdown Fusion
  81. //
  82. SHFusionUninitialize();
  83. }
  84. return TRUE;
  85. } // DllMain ()
  86. extern "C"
  87. DWORD
  88. APIENTRY
  89. ClassInstall (
  90. IN DI_FUNCTION diFunction,
  91. IN HDEVINFO hDevInfo,
  92. IN PSP_DEVINFO_DATA pDevInfoData
  93. )
  94. /*++
  95. Routine Description:
  96. ClassInstall
  97. Entrypoint of WIA class installer.
  98. Arguments:
  99. IN DI_FUNCTION diFunction Function to perform.
  100. IN HDEVINFO hDevInfo, Handle to Device Information.
  101. IN PSP_DEVINFO_DATA pDevInfoData Pointer to Device Data.
  102. Return Value:
  103. NO_ERROR - Operation succeeded.
  104. ERROR_DI_DO_DEFAULT - Operation succeeded, or failed but let it continue.
  105. Other - Operation failed and unable to continue.
  106. Side effects:
  107. None
  108. --*/
  109. {
  110. DWORD dwReturn;
  111. DWORD dwError;
  112. DWORD dwSize;
  113. SP_INSTALLWIZARD_DATA InstallWizardData;
  114. SP_DEVINSTALL_PARAMS spDevInstallParams;
  115. BOOL fCleanupContext;
  116. PINSTALLER_CONTEXT pInstallerContext;
  117. DebugTrace(TRACE_PROC_ENTER,(("ClassInstall: Enter... \r\n")));
  118. DebugTrace(TRACE_STATUS,(("ClassInstall: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
  119. //
  120. // Initialize locals.
  121. //
  122. dwReturn = ERROR_DI_DO_DEFAULT;
  123. dwError = ERROR_SUCCESS;
  124. dwSize = 0;
  125. fCleanupContext = FALSE;
  126. pInstallerContext = NULL;
  127. memset(&InstallWizardData, 0, sizeof(InstallWizardData));
  128. memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
  129. //
  130. // Dispatch requests.
  131. //
  132. switch(diFunction){
  133. case DIF_INSTALLWIZARD:
  134. {
  135. fCleanupContext = TRUE;
  136. //
  137. // Get install parameter(s).
  138. //
  139. InstallWizardData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  140. if(!SetupDiGetClassInstallParams(hDevInfo,
  141. pDevInfoData,
  142. &InstallWizardData.ClassInstallHeader,
  143. sizeof(InstallWizardData),
  144. NULL) )
  145. {
  146. dwError = GetLastError();
  147. // DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x. dwSize=0x%x\n"), dwError, dwSize));
  148. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x\n"), dwError));
  149. dwReturn = ERROR_DI_DONT_INSTALL;
  150. goto ClassInstall_return;
  151. }
  152. //
  153. // Check if operation is correct.
  154. //
  155. if (InstallWizardData.ClassInstallHeader.InstallFunction != diFunction) {
  156. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! InstallHeader.InstallFunction is incorrect..\r\n")));
  157. dwReturn = ERROR_DI_DONT_INSTALL;
  158. goto ClassInstall_return;
  159. }
  160. //
  161. // Check if we still have enough room to add pages.
  162. //
  163. if( (MAX_INSTALLWIZARD_DYNAPAGES - NUM_WIA_PAGES) < InstallWizardData.NumDynamicPages ){
  164. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No room for WIA installer pages.\r\n")));
  165. dwReturn = ERROR_DI_DONT_INSTALL;
  166. goto ClassInstall_return;
  167. }
  168. //
  169. // Allocate context structure.
  170. //
  171. if(NULL == InstallWizardData.PrivateData){
  172. pInstallerContext = new INSTALLER_CONTEXT;
  173. if(NULL == pInstallerContext){
  174. DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! Insufficient memory.\r\n")));
  175. dwReturn = ERROR_DI_DONT_INSTALL;
  176. goto ClassInstall_return;
  177. }
  178. InstallWizardData.PrivateData = (DWORD_PTR)pInstallerContext;
  179. memset((PBYTE)pInstallerContext, 0, sizeof(INSTALLER_CONTEXT));
  180. } else {
  181. DebugTrace(TRACE_WARNING,(("ClassInstall: WARNING!! Installer context already exists.\r\n")));
  182. }
  183. //
  184. // See who invoked installer.
  185. //
  186. pInstallerContext->bShowFirstPage = InstallWizardData.PrivateFlags & SCIW_PRIV_SHOW_FIRST;
  187. pInstallerContext->bCalledFromControlPanal = InstallWizardData.PrivateFlags & SCIW_PRIV_CALLED_FROMCPL;
  188. //
  189. // Save device info set.
  190. //
  191. pInstallerContext->hDevInfo = hDevInfo;
  192. //
  193. // Save wizard windows handle.
  194. //
  195. pInstallerContext->hwndWizard = InstallWizardData.hwndWizardDlg;
  196. //
  197. // Create/Initialize all wizard pages and a device class object.
  198. //
  199. CFirstPage *tempFistPage = new CFirstPage(pInstallerContext);
  200. CPrevSelectPage *tempPrevSelectPage = new CPrevSelectPage(pInstallerContext);
  201. CPortSelectPage *tempPortSelectPage = new CPortSelectPage(pInstallerContext);
  202. CNameDevicePage *tempNameDevicePage = new CNameDevicePage(pInstallerContext);
  203. CInstallPage *tempInstallPage = new CInstallPage(pInstallerContext);
  204. if( (NULL == tempFistPage)
  205. || (NULL == tempPrevSelectPage)
  206. || (NULL == tempPortSelectPage)
  207. || (NULL == tempNameDevicePage)
  208. || (NULL == tempInstallPage) )
  209. {
  210. DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! Insufficient memory.\r\n")));
  211. dwReturn = ERROR_DI_DO_DEFAULT;
  212. goto ClassInstall_return;
  213. }
  214. //
  215. // Save created to context.
  216. //
  217. pInstallerContext->pFirstPage = (PVOID) tempFistPage;
  218. pInstallerContext->pPrevSelectPage = (PVOID) tempPrevSelectPage;
  219. pInstallerContext->pPortSelectPage = (PVOID) tempPortSelectPage;
  220. pInstallerContext->pNameDevicePage = (PVOID) tempNameDevicePage;
  221. pInstallerContext->pFinalPage = (PVOID) tempInstallPage;
  222. //
  223. // Add created pages.
  224. //
  225. InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempFistPage->Handle();
  226. InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempPrevSelectPage->Handle();
  227. InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempPortSelectPage->Handle();
  228. InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempNameDevicePage->Handle();
  229. InstallWizardData.DynamicPages[InstallWizardData.NumDynamicPages++] = tempInstallPage->Handle();
  230. //
  231. // Indicate "pages are added".
  232. //
  233. InstallWizardData.DynamicPageFlags |= DYNAWIZ_FLAG_PAGESADDED;
  234. //
  235. // Set the parameters back.
  236. //
  237. SetupDiSetClassInstallParams (hDevInfo,
  238. pDevInfoData,
  239. &InstallWizardData.ClassInstallHeader,
  240. sizeof(InstallWizardData));
  241. fCleanupContext = FALSE;
  242. dwReturn = NO_ERROR;
  243. goto ClassInstall_return;
  244. break;
  245. } // case DIF_INSTALLWIZARD:
  246. case DIF_DESTROYWIZARDDATA:
  247. {
  248. //
  249. // Get install parameter(s).
  250. //
  251. InstallWizardData.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  252. if(!SetupDiGetClassInstallParams(hDevInfo,
  253. pDevInfoData,
  254. &InstallWizardData.ClassInstallHeader,
  255. sizeof(InstallWizardData),
  256. &dwSize) )
  257. {
  258. dwError = GetLastError();
  259. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed. Err=0x%x\n"), dwError));
  260. dwReturn = ERROR_DI_DO_DEFAULT;
  261. goto ClassInstall_return;
  262. }
  263. // //
  264. // // Check if operation is correct.
  265. // //
  266. //
  267. // if (InstallWizardData.ClassInstallHeader.InstallFunction != diFunction) {
  268. // DebugTrace(TRACE_WARNING,(("ClassInstall: ERROR!! InstallHeader.InstallFunction is incorrect..\r\n")));
  269. //
  270. // dwReturn = ERROR_DI_DO_DEFAULT;
  271. // goto ClassInstall_return;
  272. // }
  273. //
  274. // Free all allocated resources.
  275. //
  276. fCleanupContext = TRUE;
  277. pInstallerContext = (PINSTALLER_CONTEXT)InstallWizardData.PrivateData;
  278. InstallWizardData.PrivateData = NULL;
  279. dwReturn = NO_ERROR;
  280. goto ClassInstall_return;
  281. break;
  282. } // case DIF_DESTROYWIZARDDATA:
  283. case DIF_INSTALLDEVICE:
  284. {
  285. BOOL bSucceeded;
  286. BOOL bIsPnp;
  287. //
  288. // Sanity check of DevInfoSet and DevInfoData.
  289. //
  290. if( (NULL == pDevInfoData)
  291. || (!IS_VALID_HANDLE(hDevInfo)) )
  292. {
  293. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Wrong Infoset(0x%x) or instance(0x%x). Unable to continue.\r\n"),pDevInfoData,hDevInfo));
  294. dwReturn = ERROR_DI_DO_DEFAULT;
  295. goto ClassInstall_return;
  296. }
  297. //
  298. // Get device install parameters.
  299. //
  300. memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
  301. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  302. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  303. pDevInfoData,
  304. &spDevInstallParams))
  305. {
  306. DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), GetLastError()));
  307. dwReturn = ERROR_DI_DO_DEFAULT;
  308. goto ClassInstall_return;
  309. }
  310. //
  311. // Check NULL driver installation.
  312. //
  313. if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL){
  314. //
  315. // Installing NULL driver. Let default handler handle it.
  316. //
  317. dwReturn = ERROR_DI_DO_DEFAULT;
  318. goto ClassInstall_return;
  319. } // if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
  320. //
  321. // See if it's root-enumerated or not.
  322. //
  323. if(IsDeviceRootEnumerated(hDevInfo, pDevInfoData)){
  324. bIsPnp = FALSE;
  325. } else {
  326. bIsPnp = TRUE;
  327. }
  328. //
  329. // Create CDevice class.
  330. //
  331. //
  332. // Start the WIA service. We start it here so that it will be running when we finish, so
  333. // it will receive the PnP device arrival notification.
  334. // Notice we don't change the startup-type here - this will be done later if the device
  335. // installation was successful.
  336. //
  337. StartWiaService();
  338. CDevice cdThis(hDevInfo, pDevInfoData, bIsPnp);
  339. //
  340. // Let it create unique FriendlyName.
  341. //
  342. bSucceeded = cdThis.NameDefaultUniqueName();
  343. if(bSucceeded){
  344. //
  345. // Do pre-installation process.
  346. //
  347. bSucceeded = cdThis.PreInstall();
  348. if(bSucceeded){
  349. //
  350. // Do actual installation.
  351. //
  352. bSucceeded = cdThis.Install();
  353. if(!bSucceeded){
  354. dwReturn = ERROR_DI_DONT_INSTALL;
  355. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Installation failed in CDevice class.\r\n")));
  356. }
  357. } else {
  358. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PreInstall failed in CDevice class.\r\n")));
  359. }
  360. } else {
  361. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
  362. dwReturn = ERROR_DI_DONT_INSTALL;
  363. }
  364. if(bSucceeded){
  365. //
  366. // So far, installation is working fine. Do final touch.
  367. //
  368. bSucceeded = cdThis.PostInstall(TRUE);
  369. if(!bSucceeded){
  370. dwReturn = ERROR_DI_DONT_INSTALL;
  371. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PostInstall failed in CDevice class.\r\n")));
  372. }
  373. //
  374. // At this point, we consider the installation is succeeded.
  375. //
  376. dwReturn = NO_ERROR;
  377. //
  378. // Get device install parameters again.
  379. //
  380. memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
  381. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  382. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  383. pDevInfoData,
  384. &spDevInstallParams))
  385. {
  386. dwReturn = GetLastError();;
  387. DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
  388. goto ClassInstall_return;
  389. }
  390. //
  391. // We need to notify WIA service about new device addition.
  392. //
  393. if(NULL == spDevInstallParams.ClassInstallReserved){
  394. spDevInstallParams.ClassInstallReserved = (ULONG_PTR)new CLEANUPITEM;
  395. if(NULL != spDevInstallParams.ClassInstallReserved){
  396. memset((PVOID)(spDevInstallParams.ClassInstallReserved), 0, sizeof(CLEANUPITEM));
  397. } else { // if(NULL == spDevInstallParams.ClassInstallReserved)
  398. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate CLEANUPITEM.\r\n")));
  399. }
  400. } // if(NULL == spDevInstallParams.ClassInstallReserved)
  401. if(NULL != spDevInstallParams.ClassInstallReserved){
  402. ((PCLEANUPITEM)spDevInstallParams.ClassInstallReserved)->bInstalled = TRUE;
  403. if(SetupDiSetDeviceInstallParams(hDevInfo,
  404. pDevInfoData,
  405. &spDevInstallParams))
  406. {
  407. //
  408. // Installation succeeded.
  409. //
  410. DebugTrace(TRACE_STATUS,(("ClassInstall: WIA service will reenumerate device.\r\n")));
  411. } else {
  412. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
  413. }
  414. } else { // if(NULL != spDevInstallParams.ClassInstallReserved)
  415. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No CLEANUPITEM in context.\r\n")));
  416. } // else(NULL != spDevInstallParams.ClassInstallReserved)
  417. } else {
  418. //
  419. // There's an error during installation. Revert.
  420. //
  421. cdThis.PostInstall(FALSE);
  422. dwReturn = ERROR_DI_DONT_INSTALL;
  423. DebugTrace(TRACE_ERROR,(("ClassInstall: Reverting installation...\r\n")));
  424. }
  425. goto ClassInstall_return;
  426. break;
  427. } // case DIF_INSTALLDEVICE:
  428. case DIF_REMOVE:
  429. {
  430. SP_REMOVEDEVICE_PARAMS rdp;
  431. //
  432. // Check if operation is correct.
  433. //
  434. memset (&rdp, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
  435. rdp.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER);
  436. if (!SetupDiGetClassInstallParams (hDevInfo,
  437. pDevInfoData,
  438. &rdp.ClassInstallHeader,
  439. sizeof(SP_REMOVEDEVICE_PARAMS),
  440. NULL))
  441. {
  442. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed Err=0x%x.\r\n"), GetLastError()));
  443. dwReturn = ERROR_DI_DO_DEFAULT;
  444. goto ClassInstall_return;
  445. } // if (!SetupDiGetClassInstallParams ()
  446. if (rdp.ClassInstallHeader.InstallFunction != DIF_REMOVE) {
  447. dwReturn = ERROR_DI_DO_DEFAULT;
  448. goto ClassInstall_return;
  449. }
  450. //
  451. // Create CDevice object.
  452. //
  453. CDevice cdThis(hDevInfo, pDevInfoData, TRUE);
  454. //
  455. // Remove the device.
  456. //
  457. dwReturn = cdThis.Remove(&rdp);
  458. //
  459. // Get device install parameters.
  460. //
  461. memset(&spDevInstallParams, 0, sizeof(spDevInstallParams));
  462. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  463. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  464. pDevInfoData,
  465. &spDevInstallParams))
  466. {
  467. dwReturn = GetLastError();;
  468. DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
  469. goto ClassInstall_return;
  470. }
  471. //
  472. // We need to notify WIA service about new device addition.
  473. //
  474. if(NULL == spDevInstallParams.ClassInstallReserved){
  475. spDevInstallParams.ClassInstallReserved = (ULONG_PTR)new CLEANUPITEM;
  476. if(NULL != spDevInstallParams.ClassInstallReserved){
  477. memset((PVOID)(spDevInstallParams.ClassInstallReserved), 0, sizeof(CLEANUPITEM));
  478. } else { // if(NULL == spDevInstallParams.ClassInstallReserved)
  479. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate CLEANUPITEM.\r\n")));
  480. }
  481. } // if(NULL == spDevInstallParams.ClassInstallReserved)
  482. if(NULL != spDevInstallParams.ClassInstallReserved){
  483. ((PCLEANUPITEM)spDevInstallParams.ClassInstallReserved)->bRemoved = TRUE;
  484. if(SetupDiSetDeviceInstallParams(hDevInfo,
  485. pDevInfoData,
  486. &spDevInstallParams))
  487. {
  488. //
  489. // Installation succeeded.
  490. //
  491. DebugTrace(TRACE_STATUS,(("ClassInstall: WIA service will reenumerate device.\r\n")));
  492. } else {
  493. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiSetDeviceInstallParams() failed. Err=0x%x.\r\n"), GetLastError()));
  494. }
  495. } else { // if(NULL != spDevInstallParams.ClassInstallReserved)
  496. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! No CLEANUPITEM in context.\r\n")));
  497. } // else(NULL != spDevInstallParams.ClassInstallReserved)
  498. goto ClassInstall_return;
  499. break;
  500. } // case DIF_REMOVE:
  501. case DIF_SELECTBESTCOMPATDRV:
  502. {
  503. SP_DRVINSTALL_PARAMS spDriverInstallParams;
  504. SP_DRVINFO_DATA spDriverInfoData;
  505. PSP_DRVINFO_DETAIL_DATA pspDriverInfoDetailData;
  506. DWORD dwLastError;
  507. DWORD dwSizeLocal;
  508. DWORD Idx;
  509. //
  510. // Get driver info.
  511. //
  512. memset(&spDriverInfoData, 0, sizeof(spDriverInfoData));
  513. spDriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  514. for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData); Idx++){
  515. //
  516. // Get driver install params.
  517. //
  518. memset(&spDriverInstallParams, 0, sizeof(spDriverInstallParams));
  519. spDriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  520. if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams)){
  521. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInstallParams() failed LastError=0x%x.\r\n", GetLastError()));
  522. dwReturn = ERROR_DI_DO_DEFAULT;
  523. goto ClassInstall_return;
  524. } // if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams))
  525. //
  526. // Get buffer size required for driver derail data.
  527. //
  528. dwSizeLocal = 0;
  529. SetupDiGetDriverInfoDetail(hDevInfo,
  530. pDevInfoData,
  531. &spDriverInfoData,
  532. NULL,
  533. 0,
  534. &dwSizeLocal);
  535. dwLastError = GetLastError();
  536. if(ERROR_INSUFFICIENT_BUFFER != dwLastError){
  537. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() doesn't return required size.Er=0x%x\r\n"),dwLastError));
  538. dwReturn = ERROR_DI_DO_DEFAULT;
  539. goto ClassInstall_return;
  540. } // if(ERROR_INSUFFICIENT_BUFFER != dwLastError)
  541. //
  542. // Allocate required size of buffer for driver detailed data.
  543. //
  544. pspDriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)new char[dwSizeLocal];
  545. if(NULL == pspDriverInfoDetailData){
  546. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate driver detailed info buffer.\r\n")));
  547. dwReturn = ERROR_DI_DO_DEFAULT;
  548. goto ClassInstall_return;
  549. } // if(NULL == pspDriverInfoDetailData)
  550. //
  551. // Initialize allocated buffer.
  552. //
  553. memset(pspDriverInfoDetailData, 0, dwSizeLocal);
  554. pspDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  555. //
  556. // Get detailed data of selected device driver.
  557. //
  558. if(!SetupDiGetDriverInfoDetail(hDevInfo,
  559. pDevInfoData,
  560. &spDriverInfoData,
  561. pspDriverInfoDetailData,
  562. dwSizeLocal,
  563. NULL) )
  564. {
  565. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() failed LastError=0x%x.\r\n", GetLastError()));
  566. delete[] pspDriverInfoDetailData;
  567. continue;
  568. } // if(NULL == pspDriverInfoDetailData)
  569. //
  570. // See if INF filename is valid.
  571. //
  572. if(NULL == pspDriverInfoDetailData->InfFileName){
  573. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() returned invalid INF name.\r\n"));
  574. delete[] pspDriverInfoDetailData;
  575. continue;
  576. } // if(NULL == pspDriverInfoDetailData->InfFileName)
  577. //
  578. // If it's Inbox driver, set DNF_BASIC_DRIVER.
  579. //
  580. if( IsWindowsFile(pspDriverInfoDetailData->InfFileName)
  581. && IsProviderMs(pspDriverInfoDetailData->InfFileName ) )
  582. {
  583. //
  584. // This is inbox INF. set DNF_BASIC_DRIVER.
  585. //
  586. spDriverInstallParams.Flags |= DNF_BASIC_DRIVER;
  587. SetupDiSetDriverInstallParams(hDevInfo,
  588. pDevInfoData,
  589. &spDriverInfoData,
  590. &spDriverInstallParams);
  591. } // if(IsWindowsFilw() && IsProviderMs())
  592. //
  593. // Clean up.
  594. //
  595. delete[] pspDriverInfoDetailData;
  596. } // for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData), Idx++)
  597. goto ClassInstall_return;
  598. break;
  599. } // case DIF_SELECTBESTCOMPATDRV:
  600. case DIF_DESTROYPRIVATEDATA:
  601. {
  602. PCLEANUPITEM pCleanupItem;
  603. //
  604. // Get device install parameters.
  605. //
  606. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  607. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  608. pDevInfoData,
  609. &spDevInstallParams))
  610. {
  611. dwReturn = GetLastError();;
  612. DebugTrace(TRACE_STATUS,(("ClassInstall: SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), dwReturn));
  613. goto ClassInstall_return;
  614. }
  615. //
  616. // See if any cleanup required.
  617. //
  618. pCleanupItem = (PCLEANUPITEM)spDevInstallParams.ClassInstallReserved;
  619. if(NULL != pCleanupItem){
  620. //
  621. // A device is installed/uninstalled.
  622. //
  623. DebugTrace(TRACE_STATUS,("ClassInstall: Clean up item is created..\r\n"));
  624. if( (TRUE == pCleanupItem->bInstalled)
  625. || (TRUE == pCleanupItem->bRemoved) )
  626. {
  627. DebugTrace(TRACE_STATUS,("ClassInstall: Let WIA service refresh device list.\r\n"));
  628. WiaDeviceEnum();
  629. }
  630. delete pCleanupItem;
  631. pCleanupItem = NULL;
  632. } // if(NULL != pCleanupItem)
  633. } // case DIF_DESTROYPRIVATEDATA:
  634. // case DIF_ENABLECLASS:
  635. // case DIF_FIRSTTIMESETUP:
  636. default:
  637. break;
  638. } // switch(diFunction)
  639. ClassInstall_return:
  640. if(fCleanupContext){
  641. if(NULL != pInstallerContext){
  642. if(NULL != pInstallerContext->pFirstPage){
  643. delete (CFirstPage *)(pInstallerContext->pFirstPage);
  644. }
  645. if(NULL != pInstallerContext->pPrevSelectPage){
  646. delete (CPrevSelectPage *)(pInstallerContext->pPrevSelectPage);
  647. }
  648. if(NULL != pInstallerContext->pPortSelectPage){
  649. delete (CPortSelectPage *)(pInstallerContext->pPortSelectPage);
  650. }
  651. if(NULL != pInstallerContext->pNameDevicePage){
  652. delete (CNameDevicePage *)(pInstallerContext->pNameDevicePage);
  653. }
  654. if(NULL != pInstallerContext->pFinalPage){
  655. delete (CInstallPage *)(pInstallerContext->pFinalPage);
  656. }
  657. //
  658. // Removed this delete call for the pDevice pointer. The Wizard pages
  659. // delete this memory when a user presses "cancel" or closes the Wizard
  660. // dialog.
  661. //
  662. // COOPP - 01-18-2001. Quick fix to BUG #284981 Heap Corruption
  663. //
  664. // Note for future: As discussed with KeisukeT, a better design would be
  665. // adding a shared pInstallerContext pointer in the BASE class of the
  666. // Wizard pages. This would allow this routine to remain enabled as a
  667. // "catch-all" case. (Catching the case if the Wizard dialogs did not free
  668. // the memory first)
  669. //
  670. // if(NULL != pInstallerContext->pDevice){
  671. // delete pInstallerContext->pDevice;
  672. //}
  673. //
  674. delete pInstallerContext;
  675. } // if(NULL != pInstallerContext)
  676. }
  677. DebugTrace(TRACE_PROC_LEAVE,(("ClassInstall: Leaving... Ret=0x%x.\r\n"), dwReturn));
  678. return dwReturn;
  679. } // ClassInstall()
  680. extern "C"
  681. DWORD
  682. APIENTRY
  683. CoinstallerEntry(
  684. IN DI_FUNCTION diFunction,
  685. IN HDEVINFO hDevInfo,
  686. IN PSP_DEVINFO_DATA pDevInfoData,
  687. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  688. )
  689. /*++
  690. Routine Description:
  691. CoinstallerEntry
  692. Entrypoint of WIA class coinstaller.
  693. Arguments:
  694. IN DI_FUNCTION diFunction, Function to perform.
  695. IN HDEVINFO hDevInfo, Handle to Device Information.
  696. IN PSP_DEVINFO_DATA pDevInfoData, Pointer to Device Data.
  697. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext Context data for coinstaller.
  698. Return Value:
  699. NO_ERROR - Operation succeeded.
  700. ERROR_DI_POSTPROCESSING_REQUIRED - Need post processing after installation has done.
  701. Side effects:
  702. None
  703. --*/
  704. {
  705. DWORD dwReturn;
  706. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerEntry: Enter... \r\n")));
  707. //
  708. // Initialize local.
  709. //
  710. dwReturn = NO_ERROR;
  711. //
  712. // Do Pre/Post process.
  713. //
  714. if(pCoinstallerContext->PostProcessing){
  715. //
  716. // Do post-process.
  717. //
  718. dwReturn = CoinstallerPostProcess(diFunction,
  719. hDevInfo,
  720. pDevInfoData,
  721. pCoinstallerContext);
  722. } else {
  723. //
  724. // Do pre-process.
  725. //
  726. dwReturn = CoinstallerPreProcess(diFunction,
  727. hDevInfo,
  728. pDevInfoData,
  729. pCoinstallerContext);
  730. } // if(pCoinstallerContext->PostProcessing)
  731. // CoinstallerEntry_return:
  732. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerEntry: Leaving... Ret=0x%x.\r\n"), dwReturn));
  733. return dwReturn;
  734. } // CoinstallerEntry()
  735. DWORD
  736. APIENTRY
  737. CoinstallerPreProcess(
  738. IN DI_FUNCTION diFunction,
  739. IN HDEVINFO hDevInfo,
  740. IN PSP_DEVINFO_DATA pDevInfoData,
  741. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  742. )
  743. {
  744. DWORD dwReturn;
  745. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPreProcess: Enter... \r\n")));
  746. DebugTrace(TRACE_STATUS,(("CoinstallerPreProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
  747. //
  748. // Initialize local.
  749. //
  750. dwReturn = NO_ERROR;
  751. //
  752. // Dispatch requests.
  753. //
  754. switch(diFunction){
  755. case DIF_INSTALLDEVICE:
  756. {
  757. BOOL bSucceeded;
  758. //
  759. // Initialize private data.
  760. //
  761. if(NULL != pCoinstallerContext->PrivateData){
  762. DebugTrace(TRACE_WARNING,(("CoinstallerPreProcess: WARNING!! Private has value other than NULL.\r\n")));
  763. }
  764. pCoinstallerContext->PrivateData = NULL;
  765. //
  766. // Create CDevice class.
  767. //
  768. CDevice *pDevice = new CDevice(hDevInfo, pDevInfoData, TRUE);
  769. if(NULL == pDevice){
  770. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Insufficient memory.\r\n")));
  771. dwReturn = NO_ERROR;
  772. goto CoinstallerPreProcess_return;
  773. } // if(NULL == pDevice)
  774. //
  775. // Let it create unique FriendlyName.
  776. //
  777. bSucceeded = pDevice->NameDefaultUniqueName();
  778. if(bSucceeded){
  779. //
  780. // Do pre-installation process.
  781. //
  782. bSucceeded = pDevice->PreInstall();
  783. if(!bSucceeded){
  784. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Pre-Installation failed in CDevice class.\r\n")));
  785. delete pDevice;
  786. dwReturn = NO_ERROR;
  787. goto CoinstallerPreProcess_return;
  788. }
  789. } else {
  790. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
  791. delete pDevice;
  792. dwReturn = NO_ERROR;
  793. goto CoinstallerPreProcess_return;
  794. }
  795. //
  796. // Post-installation have to free allocated object.
  797. //
  798. pCoinstallerContext->PrivateData = (PVOID)pDevice;
  799. dwReturn = ERROR_DI_POSTPROCESSING_REQUIRED;
  800. goto CoinstallerPreProcess_return;
  801. break;
  802. } // case DIF_INSTALLDEVICE:
  803. default:
  804. break;
  805. } // switch(diFunction)
  806. CoinstallerPreProcess_return:
  807. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPreProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
  808. return dwReturn;
  809. } // CoinstallerPreProcess()
  810. DWORD
  811. APIENTRY
  812. CoinstallerPostProcess(
  813. IN DI_FUNCTION diFunction,
  814. IN HDEVINFO hDevInfo,
  815. IN PSP_DEVINFO_DATA pDevInfoData,
  816. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  817. )
  818. {
  819. DWORD dwReturn;
  820. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPostProcess: Enter... \r\n")));
  821. DebugTrace(TRACE_STATUS,(("CoinstallerPostProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
  822. //
  823. // Initialize local.
  824. //
  825. dwReturn = NO_ERROR;
  826. //
  827. // Dispatch requests.
  828. //
  829. switch(diFunction){
  830. case DIF_INSTALLDEVICE:
  831. {
  832. BOOL bSucceeded;
  833. CDevice *pDevice;
  834. if(NO_ERROR == pCoinstallerContext->InstallResult){
  835. bSucceeded = TRUE;
  836. } else {
  837. bSucceeded = FALSE;
  838. }
  839. //
  840. // Get pointer to the CDevice class created in pre-process.
  841. //
  842. pDevice = (CDevice *)pCoinstallerContext->PrivateData;
  843. //
  844. // Do post-installation process.
  845. //
  846. pDevice->PostInstall(bSucceeded);
  847. //
  848. // Delete CDevice object.
  849. //
  850. delete pDevice;
  851. pCoinstallerContext->PrivateData = NULL;
  852. dwReturn = NO_ERROR;
  853. goto CoinstallerPostProcess_return;
  854. break;
  855. } // case DIF_INSTALLDEVICE:
  856. default:
  857. break;
  858. } // switch(diFunction)
  859. CoinstallerPostProcess_return:
  860. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPostProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
  861. return dwReturn;
  862. } // CoinstallerPostProcess(