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.

979 lines
30 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. spDevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  301. if(!SetupDiGetDeviceInstallParams(hDevInfo,
  302. pDevInfoData,
  303. &spDevInstallParams))
  304. {
  305. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetDeviceInstallParams failed Err=0x%x.\r\n"), GetLastError()));
  306. }
  307. if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL){
  308. //
  309. // Installing NULL driver. Let default handler handle it.
  310. //
  311. dwReturn = ERROR_DI_DO_DEFAULT;
  312. goto ClassInstall_return;
  313. } // if(spDevInstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
  314. //
  315. // See if it's root-enumerated or not.
  316. //
  317. if(IsDeviceRootEnumerated(hDevInfo, pDevInfoData)){
  318. bIsPnp = FALSE;
  319. } else {
  320. bIsPnp = TRUE;
  321. }
  322. //
  323. // Create CDevice class.
  324. //
  325. //
  326. // Start the WIA service. We start it here so that it will be running when we finish, so
  327. // it will receive the PnP device arrival notification.
  328. // Notice we don't change the startup-type here - this will be done later if the device
  329. // installation was successful.
  330. //
  331. StartWiaService();
  332. CDevice cdThis(hDevInfo, pDevInfoData, bIsPnp);
  333. //
  334. // Let it create unique FriendlyName.
  335. //
  336. bSucceeded = cdThis.NameDefaultUniqueName();
  337. if(bSucceeded){
  338. //
  339. // Do pre-installation process.
  340. //
  341. bSucceeded = cdThis.PreInstall();
  342. if(bSucceeded){
  343. //
  344. // Do actual installation.
  345. //
  346. bSucceeded = cdThis.Install();
  347. if(!bSucceeded){
  348. dwReturn = ERROR_DI_DONT_INSTALL;
  349. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Installation failed in CDevice class.\r\n")));
  350. }
  351. } else {
  352. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PreInstall failed in CDevice class.\r\n")));
  353. }
  354. } else {
  355. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
  356. dwReturn = ERROR_DI_DONT_INSTALL;
  357. }
  358. if(bSucceeded){
  359. //
  360. // So far, installation is working fine. Do final touch.
  361. //
  362. bSucceeded = cdThis.PostInstall(TRUE);
  363. if(!bSucceeded){
  364. dwReturn = ERROR_DI_DONT_INSTALL;
  365. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! PostInstall failed in CDevice class.\r\n")));
  366. }
  367. //
  368. // Installation succeeded.
  369. //
  370. dwReturn = NO_ERROR;
  371. } else {
  372. //
  373. // There's an error during installation. Revert.
  374. //
  375. cdThis.PostInstall(FALSE);
  376. dwReturn = ERROR_DI_DONT_INSTALL;
  377. DebugTrace(TRACE_ERROR,(("ClassInstall: Reverting installation...\r\n")));
  378. }
  379. goto ClassInstall_return;
  380. break;
  381. } // case DIF_INSTALLDEVICE:
  382. case DIF_REMOVE:
  383. {
  384. SP_REMOVEDEVICE_PARAMS rdp;
  385. //
  386. // Check if operation is correct.
  387. //
  388. memset (&rdp, 0, sizeof(SP_REMOVEDEVICE_PARAMS));
  389. rdp.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER);
  390. if (!SetupDiGetClassInstallParams (hDevInfo,
  391. pDevInfoData,
  392. &rdp.ClassInstallHeader,
  393. sizeof(SP_REMOVEDEVICE_PARAMS),
  394. NULL))
  395. {
  396. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetClassInstallParams failed Err=0x%x.\r\n"), GetLastError()));
  397. dwReturn = ERROR_DI_DO_DEFAULT;
  398. goto ClassInstall_return;
  399. } // if (!SetupDiGetClassInstallParams ()
  400. if (rdp.ClassInstallHeader.InstallFunction != DIF_REMOVE) {
  401. dwReturn = ERROR_DI_DO_DEFAULT;
  402. goto ClassInstall_return;
  403. }
  404. //
  405. // Create CDevice object.
  406. //
  407. CDevice cdThis(hDevInfo, pDevInfoData, TRUE);
  408. //
  409. // Remove the device.
  410. //
  411. dwReturn = cdThis.Remove(&rdp);
  412. goto ClassInstall_return;
  413. break;
  414. } // case DIF_REMOVE:
  415. case DIF_SELECTBESTCOMPATDRV:
  416. {
  417. SP_DRVINSTALL_PARAMS spDriverInstallParams;
  418. SP_DRVINFO_DATA spDriverInfoData;
  419. PSP_DRVINFO_DETAIL_DATA pspDriverInfoDetailData;
  420. DWORD dwLastError;
  421. DWORD dwSize;
  422. DWORD Idx;
  423. //
  424. // Get driver info.
  425. //
  426. memset(&spDriverInfoData, 0, sizeof(spDriverInfoData));
  427. spDriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  428. for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData); Idx++){
  429. //
  430. // Get driver install params.
  431. //
  432. memset(&spDriverInstallParams, 0, sizeof(spDriverInstallParams));
  433. spDriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  434. if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams)){
  435. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInstallParams() failed LastError=0x%x.\r\n", GetLastError()));
  436. dwReturn = ERROR_DI_DO_DEFAULT;
  437. goto ClassInstall_return;
  438. } // if(!SetupDiGetDriverInstallParams(hDevInfo, pDevInfoData, &spDriverInfoData, &spDriverInstallParams))
  439. //
  440. // Get buffer size required for driver derail data.
  441. //
  442. dwSize = 0;
  443. SetupDiGetDriverInfoDetail(hDevInfo,
  444. pDevInfoData,
  445. &spDriverInfoData,
  446. NULL,
  447. 0,
  448. &dwSize);
  449. dwLastError = GetLastError();
  450. if(ERROR_INSUFFICIENT_BUFFER != dwLastError){
  451. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() doesn't return required size.Er=0x%x\r\n"),dwLastError));
  452. dwReturn = ERROR_DI_DO_DEFAULT;
  453. goto ClassInstall_return;
  454. } // if(ERROR_INSUFFICIENT_BUFFER != dwLastError)
  455. //
  456. // Allocate required size of buffer for driver detailed data.
  457. //
  458. pspDriverInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)new char[dwSize];
  459. if(NULL == pspDriverInfoDetailData){
  460. DebugTrace(TRACE_ERROR,(("ClassInstall: ERROR!! Unable to allocate driver detailed info buffer.\r\n")));
  461. dwReturn = ERROR_DI_DO_DEFAULT;
  462. goto ClassInstall_return;
  463. } // if(NULL == pspDriverInfoDetailData)
  464. //
  465. // Initialize allocated buffer.
  466. //
  467. memset(pspDriverInfoDetailData, 0, dwSize);
  468. pspDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  469. //
  470. // Get detailed data of selected device driver.
  471. //
  472. if(!SetupDiGetDriverInfoDetail(hDevInfo,
  473. pDevInfoData,
  474. &spDriverInfoData,
  475. pspDriverInfoDetailData,
  476. dwSize,
  477. NULL) )
  478. {
  479. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() failed LastError=0x%x.\r\n", GetLastError()));
  480. delete pspDriverInfoDetailData;
  481. continue;
  482. } // if(NULL == pspDriverInfoDetailData)
  483. //
  484. // See if INF filename is valid.
  485. //
  486. if(NULL == pspDriverInfoDetailData->InfFileName){
  487. DebugTrace(TRACE_ERROR,("ClassInstall: ERROR!! SetupDiGetDriverInfoDetail() returned invalid INF name.\r\n"));
  488. delete pspDriverInfoDetailData;
  489. continue;
  490. } // if(NULL == pspDriverInfoDetailData->InfFileName)
  491. //
  492. // If it's Inbox driver, set DNF_BASIC_DRIVER.
  493. //
  494. if( IsWindowsFile(pspDriverInfoDetailData->InfFileName)
  495. && IsProviderMs(pspDriverInfoDetailData->InfFileName ) )
  496. {
  497. //
  498. // This is inbox INF. set DNF_BASIC_DRIVER.
  499. //
  500. spDriverInstallParams.Flags |= DNF_BASIC_DRIVER;
  501. SetupDiSetDriverInstallParams(hDevInfo,
  502. pDevInfoData,
  503. &spDriverInfoData,
  504. &spDriverInstallParams);
  505. } // if(IsWindowsFilw() && IsProviderMs())
  506. //
  507. // Clean up.
  508. //
  509. delete pspDriverInfoDetailData;
  510. } // for(Idx = 0; SetupDiEnumDriverInfo(hDevInfo, pDevInfoData, SPDIT_COMPATDRIVER, Idx, &spDriverInfoData), Idx++)
  511. goto ClassInstall_return;
  512. break;
  513. } // case DIF_SELECTBESTCOMPATDRV:
  514. // case DIF_ENABLECLASS:
  515. // case DIF_FIRSTTIMESETUP:
  516. default:
  517. break;
  518. } // switch(diFunction)
  519. ClassInstall_return:
  520. if(fCleanupContext){
  521. if(NULL != pInstallerContext){
  522. if(NULL != pInstallerContext->pFirstPage){
  523. delete (CFirstPage *)(pInstallerContext->pFirstPage);
  524. }
  525. if(NULL != pInstallerContext->pPrevSelectPage){
  526. delete (CPrevSelectPage *)(pInstallerContext->pPrevSelectPage);
  527. }
  528. if(NULL != pInstallerContext->pPortSelectPage){
  529. delete (CPortSelectPage *)(pInstallerContext->pPortSelectPage);
  530. }
  531. if(NULL != pInstallerContext->pNameDevicePage){
  532. delete (CNameDevicePage *)(pInstallerContext->pNameDevicePage);
  533. }
  534. if(NULL != pInstallerContext->pFinalPage){
  535. delete (CInstallPage *)(pInstallerContext->pFinalPage);
  536. }
  537. //
  538. // Removed this delete call for the pDevice pointer. The Wizard pages
  539. // delete this memory when a user presses "cancel" or closes the Wizard
  540. // dialog.
  541. //
  542. // COOPP - 01-18-2001. Quick fix to BUG #284981 Heap Corruption
  543. //
  544. // Note for future: As discussed with KeisukeT, a better design would be
  545. // adding a shared pInstallerContext pointer in the BASE class of the
  546. // Wizard pages. This would allow this routine to remain enabled as a
  547. // "catch-all" case. (Catching the case if the Wizard dialogs did not free
  548. // the memory first)
  549. //
  550. // if(NULL != pInstallerContext->pDevice){
  551. // delete pInstallerContext->pDevice;
  552. //}
  553. //
  554. delete pInstallerContext;
  555. } // if(NULL != pInstallerContext)
  556. }
  557. DebugTrace(TRACE_PROC_LEAVE,(("ClassInstall: Leaving... Ret=0x%x.\r\n"), dwReturn));
  558. return dwReturn;
  559. } // ClassInstall()
  560. extern "C"
  561. DWORD
  562. APIENTRY
  563. CoinstallerEntry(
  564. IN DI_FUNCTION diFunction,
  565. IN HDEVINFO hDevInfo,
  566. IN PSP_DEVINFO_DATA pDevInfoData,
  567. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  568. )
  569. /*++
  570. Routine Description:
  571. CoinstallerEntry
  572. Entrypoint of WIA class coinstaller.
  573. Arguments:
  574. IN DI_FUNCTION diFunction, Function to perform.
  575. IN HDEVINFO hDevInfo, Handle to Device Information.
  576. IN PSP_DEVINFO_DATA pDevInfoData, Pointer to Device Data.
  577. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext Context data for coinstaller.
  578. Return Value:
  579. NO_ERROR - Operation succeeded.
  580. ERROR_DI_POSTPROCESSING_REQUIRED - Need post processing after installation has done.
  581. Side effects:
  582. None
  583. --*/
  584. {
  585. DWORD dwReturn;
  586. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerEntry: Enter... \r\n")));
  587. //
  588. // Initialize local.
  589. //
  590. dwReturn = NO_ERROR;
  591. //
  592. // Do Pre/Post process.
  593. //
  594. if(pCoinstallerContext->PostProcessing){
  595. //
  596. // Do post-process.
  597. //
  598. dwReturn = CoinstallerPostProcess(diFunction,
  599. hDevInfo,
  600. pDevInfoData,
  601. pCoinstallerContext);
  602. } else {
  603. //
  604. // Do pre-process.
  605. //
  606. dwReturn = CoinstallerPreProcess(diFunction,
  607. hDevInfo,
  608. pDevInfoData,
  609. pCoinstallerContext);
  610. } // if(pCoinstallerContext->PostProcessing)
  611. // CoinstallerEntry_return:
  612. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerEntry: Leaving... Ret=0x%x.\r\n"), dwReturn));
  613. return dwReturn;
  614. } // CoinstallerEntry()
  615. DWORD
  616. APIENTRY
  617. CoinstallerPreProcess(
  618. IN DI_FUNCTION diFunction,
  619. IN HDEVINFO hDevInfo,
  620. IN PSP_DEVINFO_DATA pDevInfoData,
  621. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  622. )
  623. {
  624. DWORD dwReturn;
  625. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPreProcess: Enter... \r\n")));
  626. DebugTrace(TRACE_STATUS,(("CoinstallerPreProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
  627. //
  628. // Initialize local.
  629. //
  630. dwReturn = NO_ERROR;
  631. //
  632. // Dispatch requests.
  633. //
  634. switch(diFunction){
  635. case DIF_INSTALLDEVICE:
  636. {
  637. BOOL bSucceeded;
  638. //
  639. // Initialize private data.
  640. //
  641. if(NULL != pCoinstallerContext->PrivateData){
  642. DebugTrace(TRACE_WARNING,(("CoinstallerPreProcess: WARNING!! Private has value other than NULL.\r\n")));
  643. }
  644. pCoinstallerContext->PrivateData = NULL;
  645. //
  646. // Create CDevice class.
  647. //
  648. CDevice *pDevice = new CDevice(hDevInfo, pDevInfoData, TRUE);
  649. if(NULL == pDevice){
  650. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Insufficient memory.\r\n")));
  651. dwReturn = NO_ERROR;
  652. goto CoinstallerPreProcess_return;
  653. } // if(NULL == pDevice)
  654. //
  655. // Let it create unique FriendlyName.
  656. //
  657. bSucceeded = pDevice->NameDefaultUniqueName();
  658. if(bSucceeded){
  659. //
  660. // Do pre-installation process.
  661. //
  662. bSucceeded = pDevice->PreInstall();
  663. if(!bSucceeded){
  664. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! Pre-Installation failed in CDevice class.\r\n")));
  665. delete pDevice;
  666. dwReturn = NO_ERROR;
  667. goto CoinstallerPreProcess_return;
  668. }
  669. } else {
  670. DebugTrace(TRACE_ERROR,(("CoinstallerPreProcess: ERROR!! NameDefaultUniqueName failed in CDevice class.\r\n")));
  671. delete pDevice;
  672. dwReturn = NO_ERROR;
  673. goto CoinstallerPreProcess_return;
  674. }
  675. //
  676. // Post-installation have to free allocated object.
  677. //
  678. pCoinstallerContext->PrivateData = (PVOID)pDevice;
  679. dwReturn = ERROR_DI_POSTPROCESSING_REQUIRED;
  680. goto CoinstallerPreProcess_return;
  681. break;
  682. } // case DIF_INSTALLDEVICE:
  683. default:
  684. break;
  685. } // switch(diFunction)
  686. CoinstallerPreProcess_return:
  687. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPreProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
  688. return dwReturn;
  689. } // CoinstallerPreProcess()
  690. DWORD
  691. APIENTRY
  692. CoinstallerPostProcess(
  693. IN DI_FUNCTION diFunction,
  694. IN HDEVINFO hDevInfo,
  695. IN PSP_DEVINFO_DATA pDevInfoData,
  696. IN OUT PCOINSTALLER_CONTEXT_DATA pCoinstallerContext
  697. )
  698. {
  699. DWORD dwReturn;
  700. DebugTrace(TRACE_PROC_ENTER,(("CoinstallerPostProcess: Enter... \r\n")));
  701. DebugTrace(TRACE_STATUS,(("CoinstallerPostProcess: Processing %ws message.\r\n"), DifDebug[diFunction].DifString));
  702. //
  703. // Initialize local.
  704. //
  705. dwReturn = NO_ERROR;
  706. //
  707. // Dispatch requests.
  708. //
  709. switch(diFunction){
  710. case DIF_INSTALLDEVICE:
  711. {
  712. BOOL bSucceeded;
  713. CDevice *pDevice;
  714. if(NO_ERROR == pCoinstallerContext->InstallResult){
  715. bSucceeded = TRUE;
  716. } else {
  717. bSucceeded = FALSE;
  718. }
  719. //
  720. // Get pointer to the CDevice class created in pre-process.
  721. //
  722. pDevice = (CDevice *)pCoinstallerContext->PrivateData;
  723. //
  724. // Do post-installation process.
  725. //
  726. pDevice->PostInstall(bSucceeded);
  727. //
  728. // Delete CDevice object.
  729. //
  730. delete pDevice;
  731. pCoinstallerContext->PrivateData = NULL;
  732. dwReturn = NO_ERROR;
  733. goto CoinstallerPostProcess_return;
  734. break;
  735. } // case DIF_INSTALLDEVICE:
  736. default:
  737. break;
  738. } // switch(diFunction)
  739. CoinstallerPostProcess_return:
  740. DebugTrace(TRACE_PROC_LEAVE,(("CoinstallerPostProcess: Leaving... Ret=0x%x.\r\n"), dwReturn));
  741. return dwReturn;
  742. } // CoinstallerPostProcess(