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.

1207 lines
33 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Utildi.c
  6. Abstract:
  7. Driver Setup DeviceInstaller Utility functions
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 06-Sep-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. static const GUID GUID_DEVCLASS_PRINTER =
  14. { 0x4d36e979L, 0xe325, 0x11ce,
  15. { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
  16. BOOL
  17. SetSelectDevParams(
  18. IN HDEVINFO hDevInfo,
  19. IN PSP_DEVINFO_DATA pDevInfoData,
  20. IN BOOL bWin95,
  21. IN LPCTSTR pszModel OPTIONAL
  22. )
  23. /*++
  24. Routine Description:
  25. Sets the select device parameters by calling setup apis
  26. Arguments:
  27. hDevInfo : Handle to the printer class device information list
  28. bWin95 : TRUE if selecting Win95 driver, else WinNT driver
  29. pszModel : Printer model we are looking for -- only for Win95 case
  30. Return Value:
  31. TRUE on success
  32. FALSE else
  33. --*/
  34. {
  35. SP_SELECTDEVICE_PARAMS SelectDevParams = {0};
  36. LPTSTR pszWin95Instn;
  37. SelectDevParams.ClassInstallHeader.cbSize
  38. = sizeof(SelectDevParams.ClassInstallHeader);
  39. SelectDevParams.ClassInstallHeader.InstallFunction
  40. = DIF_SELECTDEVICE;
  41. //
  42. // Get current SelectDevice parameters, and then set the fields
  43. // we want to be different from default
  44. //
  45. if ( !SetupDiGetClassInstallParams(
  46. hDevInfo,
  47. pDevInfoData,
  48. &SelectDevParams.ClassInstallHeader,
  49. sizeof(SelectDevParams),
  50. NULL) ) {
  51. if ( GetLastError() != ERROR_NO_CLASSINSTALL_PARAMS )
  52. return FALSE;
  53. ZeroMemory(&SelectDevParams, sizeof(SelectDevParams)); // NEEDED 10/11 ?
  54. SelectDevParams.ClassInstallHeader.cbSize
  55. = sizeof(SelectDevParams.ClassInstallHeader);
  56. SelectDevParams.ClassInstallHeader.InstallFunction
  57. = DIF_SELECTDEVICE;
  58. }
  59. //
  60. // Set the strings to use on the select driver page ..
  61. //
  62. if(!LoadString(ghInst,
  63. IDS_PRINTERWIZARD,
  64. SelectDevParams.Title,
  65. SIZECHARS(SelectDevParams.Title)))
  66. {
  67. return FALSE;
  68. }
  69. //
  70. // For Win95 drivers instructions are different than NT drivers
  71. //
  72. if ( bWin95 ) {
  73. pszWin95Instn = GetStringFromRcFile(IDS_WIN95DEV_INSTRUCT);
  74. if ( !pszWin95Instn )
  75. return FALSE;
  76. if ( lstrlen(pszWin95Instn) + lstrlen(pszModel) + 1
  77. > sizeof(SelectDevParams.Instructions) ) {
  78. LocalFreeMem(pszWin95Instn);
  79. return FALSE;
  80. }
  81. StringCchPrintf(SelectDevParams.Instructions, COUNTOF(SelectDevParams.Instructions), pszWin95Instn, pszModel);
  82. LocalFreeMem(pszWin95Instn);
  83. pszWin95Instn = NULL;
  84. } else {
  85. if(!LoadString(ghInst,
  86. IDS_WINNTDEV_INSTRUCT,
  87. SelectDevParams.Instructions,
  88. SIZECHARS(SelectDevParams.Instructions)))
  89. {
  90. return FALSE;
  91. }
  92. }
  93. if(!LoadString(ghInst,
  94. IDS_SELECTDEV_LABEL,
  95. SelectDevParams.ListLabel,
  96. SIZECHARS(SelectDevParams.ListLabel)))
  97. {
  98. return FALSE;
  99. }
  100. return SetupDiSetClassInstallParams(
  101. hDevInfo,
  102. pDevInfoData,
  103. &SelectDevParams.ClassInstallHeader,
  104. sizeof(SelectDevParams));
  105. }
  106. BOOL
  107. PSetupSetSelectDevTitleAndInstructions(
  108. HDEVINFO hDevInfo,
  109. LPCTSTR pszTitle,
  110. LPCTSTR pszSubTitle,
  111. LPCTSTR pszInstn
  112. )
  113. /*++
  114. Routine Description:
  115. Sets title, subtitle and instructions for the Add Printer/Add Printer Driver dialogs.
  116. Arguments:
  117. hDevInfo : Handle to the printer class device information list
  118. pszTitle : Title
  119. pszSubTitle : Subtitle
  120. pszInstn : Instructions
  121. Return Value:
  122. TRUE on success, FALSE on error
  123. --*/
  124. {
  125. SP_SELECTDEVICE_PARAMS SelectDevParams;
  126. if ( pszTitle && lstrlen(pszTitle) + 1 > MAX_TITLE_LEN ) {
  127. SetLastError(ERROR_INVALID_PARAMETER);
  128. return FALSE;
  129. }
  130. if ( pszSubTitle && lstrlen(pszSubTitle) + 1 > MAX_SUBTITLE_LEN ) {
  131. SetLastError(ERROR_INVALID_PARAMETER);
  132. return FALSE;
  133. }
  134. if ( pszInstn && lstrlen(pszInstn) + 1 > MAX_INSTRUCTION_LEN ) {
  135. SetLastError(ERROR_INVALID_PARAMETER);
  136. return FALSE;
  137. }
  138. SelectDevParams.ClassInstallHeader.cbSize
  139. = sizeof(SelectDevParams.ClassInstallHeader);
  140. SelectDevParams.ClassInstallHeader.InstallFunction
  141. = DIF_SELECTDEVICE;
  142. if ( !SetupDiGetClassInstallParams(hDevInfo,
  143. NULL,
  144. &SelectDevParams.ClassInstallHeader,
  145. sizeof(SelectDevParams),
  146. NULL) )
  147. return FALSE;
  148. if ( pszTitle )
  149. StringCchCopy(SelectDevParams.Title, COUNTOF(SelectDevParams.Title), pszTitle);
  150. if ( pszSubTitle )
  151. StringCchCopy(SelectDevParams.SubTitle, COUNTOF(SelectDevParams.SubTitle), pszSubTitle);
  152. if ( pszInstn )
  153. StringCchCopy(SelectDevParams.Instructions, COUNTOF(SelectDevParams.Instructions), pszInstn);
  154. return SetupDiSetClassInstallParams(
  155. hDevInfo,
  156. NULL,
  157. &SelectDevParams.ClassInstallHeader,
  158. sizeof(SelectDevParams));
  159. }
  160. BOOL
  161. PSetupSelectDeviceButtons(
  162. HDEVINFO hDevInfo,
  163. DWORD dwFlagsSet,
  164. DWORD dwFlagsClear
  165. )
  166. /*++
  167. Routine Description:
  168. Determines if the "Have Disk" and "Windows Update" buttons are to be displayed
  169. on the Select Device page.
  170. Arguments:
  171. hDevInfo : Handle to the printer class device information list
  172. dwFlagsSet : Flags to set
  173. dwFlagsClear : Flags to clean
  174. Return Value:
  175. TRUE on success, FALSE otherwise
  176. --*/
  177. {
  178. PSP_DEVINFO_DATA pDevInfoData = NULL;
  179. SP_DEVINSTALL_PARAMS DevInstallParams;
  180. // Check that no flags are both set & cleared
  181. if (dwFlagsSet & dwFlagsClear)
  182. {
  183. SetLastError(ERROR_INVALID_PARAMETER);
  184. return FALSE;
  185. }
  186. //
  187. // Get current SelectDevice parameters, and then set the fields
  188. // we wanted changed from default
  189. //
  190. DevInstallParams.cbSize = sizeof(DevInstallParams);
  191. if ( !SetupDiGetDeviceInstallParams(hDevInfo,
  192. pDevInfoData,
  193. &DevInstallParams) ) {
  194. return FALSE;
  195. }
  196. //
  197. // Set Flag based on Argument for Web Button
  198. if ( dwFlagsSet & SELECT_DEVICE_FROMWEB )
  199. DevInstallParams.FlagsEx |= DI_FLAGSEX_SHOWWINDOWSUPDATE;
  200. if ( dwFlagsClear & SELECT_DEVICE_FROMWEB )
  201. DevInstallParams.FlagsEx &= ~DI_FLAGSEX_SHOWWINDOWSUPDATE;
  202. if ( dwFlagsSet & SELECT_DEVICE_HAVEDISK )
  203. DevInstallParams.Flags |= DI_SHOWOEM;
  204. if ( dwFlagsClear & SELECT_DEVICE_HAVEDISK )
  205. DevInstallParams.Flags &= ~DI_SHOWOEM;
  206. return SetupDiSetDeviceInstallParams(hDevInfo,
  207. pDevInfoData,
  208. &DevInstallParams);
  209. }
  210. BOOL
  211. SetDevInstallParams(
  212. IN HDEVINFO hDevInfo,
  213. IN PSP_DEVINFO_DATA pDevInfoData,
  214. IN LPCTSTR pszDriverPath OPTIONAL
  215. )
  216. /*++
  217. Routine Description:
  218. Sets the device installation parameters by calling setup apis
  219. Arguments:
  220. hDevInfo : Handle to the printer class device information list
  221. pszDriverPath : Path where INF file should be searched
  222. Return Value:
  223. TRUE on success
  224. FALSE else
  225. --*/
  226. {
  227. SP_DEVINSTALL_PARAMS DevInstallParams;
  228. //
  229. // Get current SelectDevice parameters, and then set the fields
  230. // we wanted changed from default
  231. //
  232. DevInstallParams.cbSize = sizeof(DevInstallParams);
  233. if ( !SetupDiGetDeviceInstallParams(hDevInfo,
  234. pDevInfoData,
  235. &DevInstallParams) ) {
  236. return FALSE;
  237. }
  238. //
  239. // Drivers are class drivers,
  240. // ntprint.inf is sorted do not waste time sorting,
  241. // show Have Disk button,
  242. // use our strings on the select driver page
  243. //
  244. DevInstallParams.Flags |= DI_SHOWCLASS | DI_INF_IS_SORTED
  245. | DI_SHOWOEM
  246. | DI_USECI_SELECTSTRINGS;
  247. if ( pszDriverPath && *pszDriverPath )
  248. StringCchCopy(DevInstallParams.DriverPath, COUNTOF(DevInstallParams.DriverPath), pszDriverPath);
  249. return SetupDiSetDeviceInstallParams(hDevInfo,
  250. pDevInfoData,
  251. &DevInstallParams);
  252. }
  253. BOOL
  254. PSetupBuildDriversFromPath(
  255. IN HDEVINFO hDevInfo,
  256. IN LPCTSTR pszDriverPath,
  257. IN BOOL bEnumSingleInf
  258. )
  259. /*++
  260. Routine Description:
  261. Builds the list of printer drivers from infs from a specified path.
  262. Path could specify a directory or a single inf.
  263. Arguments:
  264. hDevInfo : Handle to the printer class device information list
  265. pszDriverPath : Path where INF file should be searched
  266. bEnumSingleInf : If TRUE pszDriverPath is a filename instead of path
  267. Return Value:
  268. TRUE on success
  269. FALSE else
  270. --*/
  271. {
  272. SP_DEVINSTALL_PARAMS DevInstallParams;
  273. //
  274. // Get current SelectDevice parameters, and then set the fields
  275. // we wanted changed from default
  276. //
  277. DevInstallParams.cbSize = sizeof(DevInstallParams);
  278. if ( !SetupDiGetDeviceInstallParams(hDevInfo,
  279. NULL,
  280. &DevInstallParams) ) {
  281. return FALSE;
  282. }
  283. DevInstallParams.Flags |= DI_INF_IS_SORTED;
  284. if ( bEnumSingleInf )
  285. DevInstallParams.Flags |= DI_ENUMSINGLEINF;
  286. StringCchCopy(DevInstallParams.DriverPath, COUNTOF(DevInstallParams.DriverPath), pszDriverPath);
  287. SetupDiDestroyDriverInfoList(hDevInfo,
  288. NULL,
  289. SPDIT_CLASSDRIVER);
  290. return SetupDiSetDeviceInstallParams(hDevInfo,
  291. NULL,
  292. &DevInstallParams) &&
  293. SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
  294. }
  295. BOOL
  296. DestroyOnlyPrinterDeviceInfoList(
  297. IN HDEVINFO hDevInfo
  298. )
  299. /*++
  300. Routine Description:
  301. This routine should be called at the end to destroy the printer device
  302. info list
  303. Arguments:
  304. hDevInfo : Handle to the printer class device information list
  305. Return Value:
  306. TRUE on success, FALSE on error
  307. --*/
  308. {
  309. return hDevInfo == INVALID_HANDLE_VALUE
  310. ? TRUE : SetupDiDestroyDeviceInfoList(hDevInfo);
  311. }
  312. BOOL
  313. PSetupDestroyPrinterDeviceInfoList(
  314. IN HDEVINFO hDevInfo
  315. )
  316. /*++
  317. Routine Description:
  318. This routine should be called at the end to destroy the printer device
  319. info list
  320. Arguments:
  321. hDevInfo : Handle to the printer class device information list
  322. Return Value:
  323. TRUE on success, FALSE on error
  324. --*/
  325. {
  326. // Cleanup and CDM Context created by windows update.
  327. DestroyCodedownload( gpCodeDownLoadInfo );
  328. gpCodeDownLoadInfo = NULL;
  329. return DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  330. }
  331. HDEVINFO
  332. CreatePrinterDeviceInfoList(
  333. IN HWND hwnd
  334. )
  335. {
  336. return SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_PRINTER, hwnd);
  337. }
  338. HDEVINFO
  339. PSetupCreatePrinterDeviceInfoList(
  340. IN HWND hwnd
  341. )
  342. /*++
  343. Routine Description:
  344. This routine should be called at the beginning to do the initialization
  345. It returns a handle which will be used on any subsequent calls to the
  346. driver setup routines.
  347. Arguments:
  348. None
  349. Return Value:
  350. On success a handle to an empty printer device information set.
  351. If the function fails INVALID_HANDLE_VALUE is returned
  352. --*/
  353. {
  354. HDEVINFO hDevInfo;
  355. hDevInfo = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_PRINTER, hwnd);
  356. if ( hDevInfo != INVALID_HANDLE_VALUE ) {
  357. if ( !SetSelectDevParams(hDevInfo, NULL, FALSE, NULL) ||
  358. !SetDevInstallParams(hDevInfo, NULL, NULL) ) {
  359. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  360. hDevInfo = INVALID_HANDLE_VALUE;
  361. }
  362. }
  363. return hDevInfo;
  364. }
  365. HPROPSHEETPAGE
  366. PSetupCreateDrvSetupPage(
  367. IN HDEVINFO hDevInfo,
  368. IN HWND hwnd
  369. )
  370. /*++
  371. Routine Description:
  372. Returns the print driver selection property page
  373. Arguments:
  374. hDevInfo : Handle to the printer class device information list
  375. hwnd : Window handle that owns the UI
  376. Return Value:
  377. Handle to the property page, NULL on failure -- use GetLastError()
  378. --*/
  379. {
  380. SP_INSTALLWIZARD_DATA InstallWizardData;
  381. ZeroMemory(&InstallWizardData, sizeof(InstallWizardData));
  382. InstallWizardData.ClassInstallHeader.cbSize
  383. = sizeof(InstallWizardData.ClassInstallHeader);
  384. InstallWizardData.ClassInstallHeader.InstallFunction
  385. = DIF_INSTALLWIZARD;
  386. InstallWizardData.DynamicPageFlags = DYNAWIZ_FLAG_PAGESADDED;
  387. InstallWizardData.hwndWizardDlg = hwnd;
  388. return SetupDiGetWizardPage(hDevInfo,
  389. NULL,
  390. &InstallWizardData,
  391. SPWPT_SELECTDEVICE,
  392. 0);
  393. }
  394. PPSETUP_LOCAL_DATA
  395. BuildInternalData(
  396. IN HDEVINFO hDevInfo,
  397. IN PSP_DEVINFO_DATA pSpDevInfoData
  398. )
  399. /*++
  400. Routine Description:
  401. Fills out the selected driver info in the SELECTED_DRV_INFO structure
  402. Arguments:
  403. hDevInfo : Handle to the printer class device information list
  404. pSpDevInfoData : Gives the selected device info element.
  405. Return Value:
  406. On success a non-NULL pointer to PSETUP_LOCAL_DATA struct
  407. NULL on error
  408. --*/
  409. {
  410. PSP_DRVINFO_DETAIL_DATA pDrvInfoDetailData;
  411. PSP_DRVINSTALL_PARAMS pDrvInstallParams;
  412. PPSETUP_LOCAL_DATA pLocalData;
  413. PSELECTED_DRV_INFO pDrvInfo;
  414. SP_DRVINFO_DATA DrvInfoData;
  415. DWORD dwNeeded;
  416. BOOL bRet = FALSE;
  417. pLocalData = (PPSETUP_LOCAL_DATA) LocalAllocMem(sizeof(*pLocalData));
  418. //
  419. // If we don't do this the call to DestroyLocalData in the cleanup code
  420. // might cause an AV.
  421. //
  422. if(pLocalData)
  423. {
  424. ZeroMemory(pLocalData, sizeof(*pLocalData));
  425. }
  426. pDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA)
  427. LocalAllocMem(sizeof(*pDrvInfoDetailData));
  428. pDrvInstallParams = (PSP_DRVINSTALL_PARAMS) LocalAllocMem(sizeof(*pDrvInstallParams));
  429. if ( !pLocalData || !pDrvInstallParams || !pDrvInfoDetailData )
  430. goto Cleanup;
  431. pDrvInfo = &pLocalData->DrvInfo;
  432. pLocalData->DrvInfo.pDevInfoData = pSpDevInfoData;
  433. pLocalData->signature = PSETUP_SIGNATURE;
  434. DrvInfoData.cbSize = sizeof(DrvInfoData);
  435. if ( !SetupDiGetSelectedDriver(hDevInfo, pSpDevInfoData, &DrvInfoData) )
  436. goto Cleanup;
  437. // Need to Check the flag in the DrvInstallParms
  438. pDrvInstallParams->cbSize = sizeof(*pDrvInstallParams);
  439. if ( !SetupDiGetDriverInstallParams(hDevInfo,
  440. pSpDevInfoData,
  441. &DrvInfoData,
  442. pDrvInstallParams) ) {
  443. goto Cleanup;
  444. }
  445. //
  446. // Did the user press the "Web" button
  447. //
  448. if ( pDrvInstallParams->Flags & DNF_INET_DRIVER )
  449. pDrvInfo->Flags |= SDFLAG_CDM_DRIVER;
  450. LocalFreeMem(pDrvInstallParams);
  451. pDrvInstallParams = NULL;
  452. dwNeeded = sizeof(*pDrvInfoDetailData);
  453. pDrvInfoDetailData->cbSize = dwNeeded;
  454. if ( !SetupDiGetDriverInfoDetail(hDevInfo,
  455. pSpDevInfoData,
  456. &DrvInfoData,
  457. pDrvInfoDetailData,
  458. dwNeeded,
  459. &dwNeeded) ) {
  460. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) {
  461. goto Cleanup;
  462. }
  463. LocalFreeMem(pDrvInfoDetailData);
  464. pDrvInfoDetailData = (PSP_DRVINFO_DETAIL_DATA) LocalAllocMem(dwNeeded);
  465. if ( !pDrvInfoDetailData )
  466. goto Cleanup;
  467. pDrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  468. if ( !SetupDiGetDriverInfoDetail(hDevInfo,
  469. pSpDevInfoData,
  470. &DrvInfoData,
  471. pDrvInfoDetailData,
  472. dwNeeded,
  473. NULL) ) {
  474. goto Cleanup;
  475. }
  476. }
  477. pDrvInfo->pszInfName = AllocStr(pDrvInfoDetailData->InfFileName);
  478. pDrvInfo->pszDriverSection = AllocStr(pDrvInfoDetailData->SectionName);
  479. pDrvInfo->pszModelName = AllocStr(DrvInfoData.Description);
  480. pDrvInfo->pszManufacturer = AllocStr(DrvInfoData.MfgName);
  481. pDrvInfo->pszProvider = AllocStr(DrvInfoData.ProviderName);
  482. pDrvInfo->ftDriverDate = DrvInfoData.DriverDate;
  483. pDrvInfo->dwlDriverVersion = DrvInfoData.DriverVersion;
  484. if ( pDrvInfoDetailData->HardwareID && *pDrvInfoDetailData->HardwareID ) {
  485. pDrvInfo->pszHardwareID = AllocStr(pDrvInfoDetailData->HardwareID);
  486. if(!pDrvInfo->pszHardwareID)
  487. goto Cleanup;
  488. }
  489. bRet = pDrvInfo->pszInfName &&
  490. pDrvInfo->pszDriverSection &&
  491. pDrvInfo->pszModelName &&
  492. pDrvInfo->pszProvider &&
  493. pDrvInfo->pszManufacturer;
  494. Cleanup:
  495. LocalFreeMem(pDrvInfoDetailData);
  496. LocalFreeMem(pDrvInstallParams);
  497. if ( bRet ) {
  498. return pLocalData;
  499. } else {
  500. //
  501. // On failure we will leave the old private local data around
  502. //
  503. DestroyLocalData(pLocalData);
  504. return NULL;
  505. }
  506. }
  507. PPSETUP_LOCAL_DATA
  508. PSetupGetSelectedDriverInfo(
  509. IN HDEVINFO hDevInfo
  510. )
  511. /**++
  512. Routine Description:
  513. Fills out the selected driver info in the SELECTED_DRV_INFO structure
  514. (inside the PPSETUP_LOCAL_DATA structure)
  515. Arguments:
  516. hDevInfo - Handle to the printer class device information list
  517. Return Value:
  518. Pointer to PSETUP_LOCAL_DATA containing information about the selected
  519. driver.
  520. --*/
  521. {
  522. return BuildInternalData(hDevInfo, NULL);
  523. }
  524. BOOL
  525. PSetupSelectDriver(
  526. IN HDEVINFO hDevInfo
  527. )
  528. /*++
  529. Routine Description:
  530. Builds the class driver list and selects a driver for the class printer driver list.
  531. Selected driver is remembered and PSetupGetSelectedDriver
  532. call will give the selected driver.
  533. Arguments:
  534. hDevInfo - Handle to the printer class device information list
  535. Return Value:
  536. TRUE on success, FALSE on error
  537. --*/
  538. {
  539. return BuildClassDriverList(hDevInfo) &&
  540. SetupDiSelectDevice(hDevInfo, NULL);
  541. }
  542. VOID
  543. GetDriverPath(
  544. IN HDEVINFO hDevInfo,
  545. IN PPSETUP_LOCAL_DATA pLocalData,
  546. OUT TCHAR szDriverPath[MAX_PATH]
  547. )
  548. /*++
  549. Routine Description:
  550. Gets the path where driver files should be searched first to copy from
  551. Arguments:
  552. pszDriverPath : Pointer to a buffer of MAX_PATH size. Gives path where
  553. system was installed from
  554. Return Value:
  555. Nothing
  556. --*/
  557. {
  558. BOOL bOemDriver = FALSE;
  559. LPTSTR *List, psz;
  560. DWORD dwCount;
  561. LPTSTR pszTempPath = NULL;
  562. //
  563. // For OEM drivers look at the place where the inf came from, else
  564. // look at the place we installed NT from
  565. //
  566. if ( pLocalData &&
  567. !(IsSystemNTPrintInf(pLocalData->DrvInfo.pszInfName) || (pLocalData->DrvInfo.Flags & SDFLAG_CDM_DRIVER ))) {
  568. StringCchCopy(szDriverPath, MAX_PATH, pLocalData->DrvInfo.pszInfName);
  569. if ( psz = FileNamePart(szDriverPath) ) {
  570. *psz = TEXT('\0');
  571. return;
  572. }
  573. }
  574. pszTempPath = GetSystemInstallPath();
  575. if ( pszTempPath != NULL )
  576. {
  577. StringCchCopy(szDriverPath, MAX_PATH, pszTempPath);
  578. LocalFreeMem(pszTempPath);
  579. }
  580. else
  581. // Default put A:\ since we have to give something to setup
  582. StringCchCopy(szDriverPath, MAX_PATH, TEXT("A:\\"));
  583. }
  584. BOOL
  585. BuildClassDriverList(
  586. IN HDEVINFO hDevInfo
  587. )
  588. /*++
  589. Routine Description:
  590. Build the class driver list.
  591. Note: If driver list is already built this comes back immediately
  592. Arguments:
  593. hDevInfo : Handle to the printer class device information list
  594. Return Value:
  595. TRUE on success, FALSE on error
  596. --*/
  597. {
  598. DWORD dwLastError;
  599. SP_DRVINFO_DATA DrvInfoData;
  600. //
  601. // Build the class driver list and also make sure there is atleast one driver
  602. //
  603. if ( !SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER) )
  604. return FALSE;
  605. DrvInfoData.cbSize = sizeof(DrvInfoData);
  606. if ( !SetupDiEnumDriverInfo(hDevInfo,
  607. NULL,
  608. SPDIT_CLASSDRIVER,
  609. 0,
  610. &DrvInfoData) &&
  611. GetLastError() == ERROR_NO_MORE_ITEMS ) {
  612. SetLastError(SPAPI_E_DI_BAD_PATH);
  613. return FALSE;
  614. }
  615. return TRUE;
  616. }
  617. BOOL
  618. IsNTPrintInf(
  619. IN LPCTSTR pszInfName
  620. )
  621. /*
  622. Function: IsNTPrintInf
  623. Purpose: Verifies is the inf file being copied is a system inf - ntprint.inf.
  624. Parameters:
  625. pszInfName - the fully qualified inf name that is being installed.
  626. Notes: This is needed to make the decision of whether to zero or even copy the inf
  627. with SetupCopyOEMInf.
  628. Should we be doing a deeper comparison than this to decide?
  629. */
  630. {
  631. BOOL bRet = FALSE;
  632. PTCHAR pFileName = FileNamePart( pszInfName );
  633. if( pFileName )
  634. {
  635. bRet = ( 0 == lstrcmpi( pFileName, cszNtprintInf ) );
  636. }
  637. return bRet;
  638. }
  639. BOOL
  640. IsSystemNTPrintInf(
  641. IN PCTSTR pszInfName
  642. )
  643. /*
  644. Function: IsSystemNTPrintInf
  645. Purpose: Verifies if the inf file the one system printer inf : %windir\inf\ntprint.inf.
  646. Parameters:
  647. pszInfName - the fully qualified inf name that is being verified.
  648. Notes: Needed to decide whether to downrank our inbox drivers
  649. */
  650. {
  651. BOOL bRet = FALSE;
  652. TCHAR szSysInf[MAX_PATH] = {0};
  653. UINT Len;
  654. PCTSTR pRelInfPath = _T("inf\\ntprint.inf");
  655. Len = GetSystemWindowsDirectory(szSysInf, MAX_PATH);
  656. if (
  657. (Len != 0) &&
  658. (Len + _tcslen(pRelInfPath) + 2 < MAX_PATH)
  659. )
  660. {
  661. if (szSysInf[Len-1] != _T('\\'))
  662. {
  663. szSysInf[Len++] = _T('\\');
  664. szSysInf[Len] = _T('\0');
  665. }
  666. StringCchCat(szSysInf, COUNTOF(szSysInf), pRelInfPath);
  667. if (!_tcsicmp(szSysInf, pszInfName))
  668. {
  669. bRet = TRUE;
  670. }
  671. }
  672. return bRet;
  673. }
  674. BOOL
  675. PSetupPreSelectDriver(
  676. IN HDEVINFO hDevInfo,
  677. IN LPCTSTR pszManufacturer,
  678. IN LPCTSTR pszModel
  679. )
  680. /*++
  681. Routine Description:
  682. Preselect a manufacturer and model for the driver dialog
  683. If same model is found select it, else if a manufacturer is given and
  684. a match in manufacturer is found select first driver for the manufacturer.
  685. If no manufacturer or model is given select the first driver.
  686. Arguments:
  687. hDevInfo : Handle to the printer class device information list
  688. pszManufacturer : Manufacterer name to preselect
  689. pszModel : Model name to preselect
  690. Return Value:
  691. TRUE on a model or manufacturer match
  692. FALSE else
  693. --*/
  694. {
  695. SP_DRVINFO_DATA DrvInfoData;
  696. DWORD dwIndex, dwManf, dwMod;
  697. if ( !BuildClassDriverList(hDevInfo) ) {
  698. return FALSE;
  699. }
  700. dwIndex = 0;
  701. //
  702. // To do only one check later
  703. //
  704. if ( pszManufacturer && !*pszManufacturer )
  705. pszManufacturer = NULL;
  706. if ( pszModel && !*pszModel )
  707. pszModel = NULL;
  708. //
  709. // If no model/manf given select first driver
  710. //
  711. if ( pszManufacturer || pszModel ) {
  712. dwManf = dwMod = MAX_DWORD;
  713. DrvInfoData.cbSize = sizeof(DrvInfoData);
  714. while ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
  715. dwIndex, &DrvInfoData) ) {
  716. if ( pszManufacturer &&
  717. dwManf == MAX_DWORD &&
  718. !lstrcmpi(pszManufacturer, DrvInfoData.MfgName) ) {
  719. dwManf = dwIndex;
  720. }
  721. if ( pszModel &&
  722. !lstrcmpi(pszModel, DrvInfoData.Description) ) {
  723. dwMod = dwIndex;
  724. break; // the for loop
  725. }
  726. DrvInfoData.cbSize = sizeof(DrvInfoData);
  727. ++dwIndex;
  728. }
  729. if ( dwMod != MAX_DWORD ) {
  730. dwIndex = dwMod;
  731. } else if ( dwManf != MAX_DWORD ) {
  732. dwIndex = dwManf;
  733. } else {
  734. SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
  735. return FALSE;
  736. }
  737. }
  738. DrvInfoData.cbSize = sizeof(DrvInfoData);
  739. if ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
  740. dwIndex, &DrvInfoData) &&
  741. SetupDiSetSelectedDriver(hDevInfo, NULL, &DrvInfoData) ) {
  742. return TRUE;
  743. }
  744. return FALSE;
  745. }
  746. PPSETUP_LOCAL_DATA
  747. PSetupDriverInfoFromName(
  748. IN HDEVINFO hDevInfo,
  749. IN LPCTSTR pszModel
  750. )
  751. /*++
  752. Routine Description:
  753. Fills out the selected driver info in the SELECTED_DRV_INFO structure
  754. (inside the PPSETUP_LOCAL_DATA structure) for the model passed into
  755. the function.
  756. Arguments:
  757. hDevInfo - Handle to the printer class device information list
  758. pszModel - Printer Driver name
  759. Return Value:
  760. Pointer to PSETUP_LOCAL_DATA containing information about pszModel
  761. --*/
  762. {
  763. return PSetupPreSelectDriver(hDevInfo, NULL, pszModel) ?
  764. BuildInternalData(hDevInfo, NULL) :
  765. NULL;
  766. }
  767. LPDRIVER_INFO_6
  768. Win95DriverInfo6FromName(
  769. IN HDEVINFO hDevInfo,
  770. IN PPSETUP_LOCAL_DATA* ppLocalData,
  771. IN LPCTSTR pszModel,
  772. IN LPCTSTR pszzPreviousNames
  773. )
  774. {
  775. LPDRIVER_INFO_6 pDriverInfo6=NULL;
  776. PPSETUP_LOCAL_DATA pLocalData;
  777. BOOL bFound;
  778. LPCTSTR pszName;
  779. if(!ppLocalData)
  780. {
  781. return FALSE;
  782. }
  783. bFound = PSetupPreSelectDriver(hDevInfo, NULL, pszModel);
  784. for ( pszName = pszzPreviousNames ;
  785. !bFound && pszName && *pszName ;
  786. pszName += lstrlen(pszName) + 1 ) {
  787. bFound = PSetupPreSelectDriver(hDevInfo, NULL, pszName);
  788. }
  789. if ( !bFound )
  790. return NULL;
  791. if ( (pLocalData = BuildInternalData(hDevInfo, NULL)) &&
  792. ParseInf(hDevInfo, pLocalData, PlatformWin95, NULL, 0, FALSE) ) {
  793. pDriverInfo6 = CloneDriverInfo6(&pLocalData->InfInfo.DriverInfo6,
  794. pLocalData->InfInfo.cbDriverInfo6);
  795. *ppLocalData = pLocalData;
  796. }
  797. if (!pDriverInfo6 && pLocalData)
  798. {
  799. DestroyLocalData(pLocalData);
  800. *ppLocalData = NULL;
  801. }
  802. return pDriverInfo6;
  803. }
  804. BOOL
  805. PSetupDestroySelectedDriverInfo(
  806. IN PPSETUP_LOCAL_DATA pLocalData
  807. )
  808. /**++
  809. Routine Description:
  810. Frees memory allocated to fields given by the pointers in the
  811. PPSETUP_LOCAL_DATA structure. Also frees the memory allocated
  812. for the structure itself.
  813. Arguments:
  814. pLocalData - Handle to the printer class device information list
  815. Return Value:
  816. Always returns TRUE
  817. --*/
  818. {
  819. ASSERT(pLocalData && pLocalData->signature == PSETUP_SIGNATURE);
  820. DestroyLocalData(pLocalData);
  821. return TRUE;
  822. }
  823. BOOL
  824. PSetupGetDriverInfForPrinter(
  825. IN HDEVINFO hDevInfo,
  826. IN LPCTSTR pszPrinterName,
  827. IN OUT LPTSTR pszInfName,
  828. IN OUT LPDWORD pcbInfNameSize
  829. )
  830. /*++
  831. Routine Description:
  832. Checks if there is an INF in %WINDIR%\inf that is identical (same driver name,
  833. same driver filename, same data file, same configuration file, same help file
  834. and same monitor name) to the driver of the printer that is passed in
  835. by comparing their DRIVER_INFO_6 structures. If such an INF is found the name
  836. of it is returned.
  837. Arguments:
  838. hDevInfo : Handle to the printer class device information list
  839. pszPrinterName : Name of printer.
  840. pszInfName : Buffer to hold name of inf file - if found
  841. pcbInfNameSize : Size of buffer pointed to by pszInfName in BYTES! Returns required size.
  842. Return Value:
  843. TRUE if INF is found
  844. FALSE else
  845. --*/
  846. {
  847. BOOL bRet = FALSE;
  848. DWORD dwSize, dwIndex;
  849. HANDLE hPrinter = NULL;
  850. LPTSTR pszInf;
  851. PPSETUP_LOCAL_DATA pLocalData = NULL;
  852. LPDRIVER_INFO_6 pDriverInfo6 = NULL;
  853. SP_DRVINFO_DATA DrvInfoData;
  854. if(!pszInfName || !pcbInfNameSize)
  855. {
  856. SetLastError(ERROR_INVALID_PARAMETER);
  857. return FALSE;
  858. }
  859. if ( !OpenPrinter((LPTSTR)pszPrinterName, &hPrinter, NULL) )
  860. return FALSE;
  861. if ( !BuildClassDriverList(hDevInfo) )
  862. goto Cleanup;
  863. GetPrinterDriver(hPrinter,
  864. NULL,
  865. 6,
  866. NULL,
  867. 0,
  868. &dwSize);
  869. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  870. goto Cleanup;
  871. if ( !((LPBYTE)pDriverInfo6 = LocalAllocMem(dwSize)) ||
  872. !GetPrinterDriver(hPrinter,
  873. NULL,
  874. 6,
  875. (LPBYTE)pDriverInfo6,
  876. dwSize,
  877. &dwSize) ) {
  878. goto Cleanup;
  879. }
  880. dwIndex = 0;
  881. DrvInfoData.cbSize = sizeof(DrvInfoData);
  882. while ( SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
  883. dwIndex, &DrvInfoData) ) {
  884. //
  885. // Is the driver name same?
  886. //
  887. if ( !lstrcmpi(pDriverInfo6->pName, DrvInfoData.Description) ) {
  888. if ( !SetupDiSetSelectedDriver(hDevInfo, NULL, &DrvInfoData) ||
  889. !(pLocalData = BuildInternalData(hDevInfo, NULL)) ||
  890. !ParseInf(hDevInfo, pLocalData, MyPlatform, NULL, 0, FALSE) ) {
  891. if ( pLocalData ) {
  892. DestroyLocalData(pLocalData);
  893. pLocalData = NULL;
  894. }
  895. break;
  896. }
  897. //
  898. // Are the DRIVER_INFO_6's identical?
  899. //
  900. if ( IdenticalDriverInfo6(&pLocalData->InfInfo.DriverInfo6,
  901. pDriverInfo6) )
  902. break;
  903. DestroyLocalData(pLocalData);
  904. pLocalData = NULL;
  905. }
  906. DrvInfoData.cbSize = sizeof(DrvInfoData);
  907. ++dwIndex;
  908. }
  909. if ( pLocalData == NULL ) {
  910. SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
  911. goto Cleanup;
  912. }
  913. pszInf= pLocalData->DrvInfo.pszInfName;
  914. dwSize = *pcbInfNameSize;
  915. *pcbInfNameSize = (lstrlen(pszInf) + 1) * sizeof(TCHAR);
  916. if ( dwSize < *pcbInfNameSize ) {
  917. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  918. goto Cleanup;
  919. }
  920. StringCbCopy(pszInfName, dwSize, pszInf);
  921. bRet = TRUE;
  922. Cleanup:
  923. ClosePrinter(hPrinter);
  924. LocalFreeMem(pDriverInfo6);
  925. DestroyLocalData(pLocalData);
  926. return bRet;
  927. }