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.

740 lines
20 KiB

  1. /*++
  2. Copyright (c) 1995-97 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Win95.c
  6. Abstract:
  7. Routines for installing win95 driver files
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 30-Nov-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. const TCHAR cszPrtupg9x[] = TEXT("prtupg9x.inf");
  14. const TCHAR cszPrinterDriverMapping[] = TEXT("Printer Driver Mapping");
  15. const TCHAR cszPrinterDriverMappingNT[] = TEXT("Printer Driver Mapping WINNT");
  16. void
  17. CutLastDirFromPath(LPTSTR pszPath)
  18. /*++
  19. Routine Description:
  20. Cuts of the last directory from a path, e.g. c:\a\b\c\f.x -> c:\a\b\f.x
  21. Arguments:
  22. pszPath : the path to operate on
  23. Return Value:
  24. none
  25. --*/
  26. {
  27. LPTSTR pLastWhack, pSecondButLastWhack;
  28. pLastWhack = _tcsrchr(pszPath, _T('\\'));
  29. if (!pLastWhack)
  30. {
  31. return;
  32. }
  33. *pLastWhack = 0;
  34. pSecondButLastWhack = _tcsrchr(pszPath, _T('\\'));
  35. if (!pSecondButLastWhack)
  36. {
  37. return;
  38. }
  39. _tcscpy(pSecondButLastWhack+1, pLastWhack+1);
  40. }
  41. BOOL
  42. CopyDriverFileAndModPath(LPTSTR pszPath)
  43. /*++
  44. Routine Description:
  45. Copies a driver file from the original location one dir up and modifies the
  46. path name accordingly
  47. Arguments:
  48. pszPath : the path of the file to copy and to operate on
  49. Return Value:
  50. TRUE if OK, FALSE on error
  51. --*/
  52. {
  53. BOOL bRes = TRUE;
  54. TCHAR *pszTmp = NULL;
  55. if (!pszPath)
  56. {
  57. goto Cleanup; // nothing to copy
  58. }
  59. pszTmp = AllocStr( pszPath );
  60. if (!pszTmp)
  61. {
  62. bRes = FALSE;
  63. goto Cleanup;
  64. }
  65. CutLastDirFromPath(pszPath);
  66. bRes = CopyFile(pszTmp, pszPath, FALSE);
  67. Cleanup:
  68. LocalFreeMem( pszTmp );
  69. return bRes;
  70. }
  71. BOOL
  72. CopyDependentFiles(LPTSTR pszzDepFiles)
  73. /*++
  74. Routine Description:
  75. Copies the dependent files one directory up and modifies the name buffers.
  76. Arguments:
  77. pszzDepFiles : the multi-sz string containing the pathes of the files to
  78. copy and to operate on
  79. Return Value:
  80. TRUE if OK, FALSE on error
  81. --*/
  82. {
  83. LPTSTR pCur = pszzDepFiles, pBuf = NULL, pCurCopy;
  84. DWORD ccBufLen;
  85. BOOL bRet = FALSE;
  86. if (pszzDepFiles == NULL)
  87. {
  88. bRet = TRUE;
  89. goto Cleanup;
  90. }
  91. //
  92. // count the total length of the buffer
  93. //
  94. for (ccBufLen = 0;
  95. *(pszzDepFiles + ccBufLen) != 0;
  96. ccBufLen += _tcslen(pszzDepFiles + ccBufLen) + 1)
  97. ;
  98. ccBufLen +=2; // for the two terminating zeros
  99. pBuf = LocalAllocMem(ccBufLen * sizeof(TCHAR));
  100. if (!pBuf)
  101. {
  102. goto Cleanup;
  103. }
  104. //
  105. // go through the source buffer file by file, modify names and copy files
  106. //
  107. for (pCur = pszzDepFiles, pCurCopy = pBuf;
  108. *pCur != 0;
  109. pCur += _tcslen(pCur) +1, pCurCopy += _tcslen(pCurCopy) +1)
  110. {
  111. _tcscpy(pCurCopy, pCur);
  112. CutLastDirFromPath(pCurCopy);
  113. if (!CopyFile(pCur, pCurCopy, FALSE))
  114. {
  115. goto Cleanup;
  116. }
  117. }
  118. //
  119. // 00-terminate the new buffer
  120. //
  121. *pCurCopy = 0;
  122. *(++pCurCopy) = 0;
  123. //
  124. // copy it back - the new version is always shorter than the original
  125. //
  126. CopyMemory(pszzDepFiles, pBuf, (pCurCopy - pBuf + 1) * sizeof(TCHAR));
  127. bRet = TRUE;
  128. Cleanup:
  129. if (pBuf)
  130. {
  131. LocalFreeMem(pBuf);
  132. }
  133. return bRet;
  134. }
  135. BOOL
  136. SetPreviousNamesSection(LPCTSTR pszServer, LPCTSTR pszModelName,
  137. LPCTSTR pszAddPrevName)
  138. /*++
  139. Routine Description:
  140. Adds a printer name to the list of previous names of a W2k/NT4 driver.
  141. This makes the driver usable under that name for point-and-print.
  142. To change the previous name section, do another call to AddPrinterDriver
  143. with all the files in place
  144. Arguments:
  145. pszServer : the machine we're operating on.
  146. pszModelName : the model name of the native driver
  147. pszAddPrevName : the name of the Win9x driver to be added to the previous
  148. names entry.
  149. Return Value:
  150. TRUE if OK, FALSE on error.
  151. --*/
  152. {
  153. PBYTE pBuf = NULL;
  154. DRIVER_INFO_6 *pDrvInfo6 = NULL;
  155. DWORD cbNeeded, cReceived, i;
  156. BOOL bRet = FALSE;
  157. LPTSTR pTmp;
  158. TCHAR pArch[MAX_PATH];
  159. //
  160. // previous names section only supported from Whistler upwards
  161. //
  162. if (!IsWhistlerOrAbove(pszServer))
  163. {
  164. bRet = TRUE;
  165. goto Cleanup;
  166. }
  167. cbNeeded = COUNTOF(pArch);
  168. if(!GetArchitecture( pszServer, pArch, &cbNeeded ))
  169. {
  170. _tcsncpy( pArch, PlatformEnv[MyPlatform].pszName, COUNTOF(pArch) );
  171. }
  172. //
  173. // Check whether the name is different in the first place
  174. //
  175. if (!_tcscmp(pszModelName, pszAddPrevName))
  176. {
  177. bRet = TRUE;
  178. goto Cleanup;
  179. }
  180. //
  181. // Get the DRIVER_INFO_6 of the W2k driver
  182. //
  183. EnumPrinterDrivers((LPTSTR) pszServer, pArch, 6, pBuf,
  184. 0, &cbNeeded, &cReceived);
  185. pBuf = LocalAllocMem(cbNeeded);
  186. if (!pBuf)
  187. {
  188. goto Cleanup;
  189. }
  190. if (!EnumPrinterDrivers((LPTSTR) pszServer, pArch, 6, pBuf,
  191. cbNeeded, &cbNeeded, &cReceived))
  192. {
  193. goto Cleanup;
  194. }
  195. for (i = 0; i < cReceived ; i++)
  196. {
  197. pDrvInfo6 = (DRIVER_INFO_6 *) (pBuf + i*sizeof(DRIVER_INFO_6));
  198. if (!_tcscmp(pszModelName, pDrvInfo6->pName))
  199. {
  200. break;
  201. }
  202. }
  203. //
  204. // was the corresponding W2k driver found ?
  205. //
  206. if (i == cReceived)
  207. {
  208. //
  209. // Couldn't find the W2k driver to set the previous names section on.
  210. // This must be the AddPrinterDriver wizard, else there would be one.
  211. // Just let the user install this driver.
  212. //
  213. bRet = TRUE;
  214. goto Cleanup;
  215. }
  216. //
  217. // check whether the name to add is already in the list
  218. //
  219. if (pDrvInfo6->pszzPreviousNames)
  220. {
  221. for (pTmp = pDrvInfo6->pszzPreviousNames; *pTmp; pTmp += _tcslen(pTmp) +1)
  222. {
  223. if (!_tcscmp(pTmp, pszAddPrevName))
  224. {
  225. bRet = TRUE;
  226. goto Cleanup;
  227. }
  228. }
  229. }
  230. //
  231. // Copy all the files into the driver dir
  232. //
  233. if (!CopyDriverFileAndModPath(pDrvInfo6->pDriverPath) ||
  234. !CopyDriverFileAndModPath(pDrvInfo6->pConfigFile) ||
  235. !CopyDriverFileAndModPath(pDrvInfo6->pDataFile) ||
  236. !CopyDriverFileAndModPath(pDrvInfo6->pHelpFile) ||
  237. !CopyDependentFiles(pDrvInfo6->pDependentFiles))
  238. {
  239. goto Cleanup;
  240. }
  241. //
  242. // Modify the PreviousNames section.
  243. // No reallocation since string lives in the same buffer as the DrvInfo6 !
  244. // +2 for the psz terminating zero and the second zero for the whole
  245. //
  246. pDrvInfo6->pszzPreviousNames = LocalAllocMem((_tcslen(pszAddPrevName) + 2) * sizeof(TCHAR));
  247. if (!pDrvInfo6->pszzPreviousNames)
  248. {
  249. goto Cleanup;
  250. }
  251. _tcscpy(pDrvInfo6->pszzPreviousNames, pszAddPrevName);
  252. //
  253. // write the driver info 6 back
  254. //
  255. bRet = AddPrinterDriver((LPTSTR) pszServer, 6, (LPBYTE) pDrvInfo6);
  256. LocalFreeMem (pDrvInfo6->pszzPreviousNames);
  257. Cleanup:
  258. if (pBuf)
  259. {
  260. LocalFreeMem (pBuf);
  261. }
  262. return bRet;
  263. }
  264. DWORD
  265. InstallWin95Driver(
  266. IN HWND hwnd,
  267. IN LPCTSTR pszModel,
  268. IN LPCTSTR pszzPreviousNames,
  269. IN BOOL bPreviousNamesSection,
  270. IN LPCTSTR pszServerName,
  271. IN OUT LPTSTR pszInfPath,
  272. IN LPCTSTR pszDiskName,
  273. IN DWORD dwInstallFlags,
  274. IN DWORD dwAddDrvFlags
  275. )
  276. /*++
  277. Routine Description:
  278. List all the printer drivers from Win95 INF files and install the
  279. printer driver selected by the user
  280. Arguments:
  281. hwnd : Window handle that owns the UI
  282. pszModel : Printer driver model
  283. pszzPreviousNames : Multi-sz string giving other names for the driver
  284. bPreviousNamesSection : If TRUE the NT inf had a Previous Names section
  285. pszServerName : Server for which driver is to be installed
  286. (NULL : local)
  287. pszInfPath : Default path for inf. Prompt will have this name
  288. for user
  289. pszDiskName : Name of the disk to prompt for and use in title
  290. dwInstallFlags : Installation flags given by caller
  291. dwAddDrvFlags : Flags for AddPrinterDriverEx
  292. Return Value:
  293. On succesfully installing files ERROR_SUCCESS, else the error code
  294. --*/
  295. {
  296. BOOL bFreeDriverName=FALSE, bFirstTime=TRUE;
  297. DWORD dwNeeded, dwRet = ERROR_CANCELLED;
  298. TCHAR szTargetPath[MAX_PATH];
  299. LPDRIVER_INFO_6 pDriverInfo6 = NULL;
  300. PPSETUP_LOCAL_DATA pLocalData = NULL;
  301. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  302. Retry:
  303. //
  304. // If we get here second time that means default path has INFs but not the
  305. // model we are looking for. Ex. an OEM driver in the previous names section
  306. // that is not on Win2K CD. So make sure we prompt
  307. //
  308. if ( !bFirstTime )
  309. {
  310. dwInstallFlags |= DRVINST_ALT_PLATFORM_INSTALL;
  311. if (pszInfPath)
  312. {
  313. *pszInfPath = 0;
  314. }
  315. }
  316. hDevInfo = GetInfAndBuildDrivers(hwnd,
  317. IDS_DRIVERS_FOR_WIN95,
  318. IDS_PROMPT_ALT_PLATFORM_DRIVER,
  319. pszInfPath,
  320. dwInstallFlags, PlatformWin95, 0,
  321. NULL, NULL, NULL);
  322. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  323. !SetSelectDevParams(hDevInfo, NULL, TRUE, pszModel) ) {
  324. goto Cleanup;
  325. }
  326. //
  327. // First look for an exact model match.
  328. //
  329. // If previous name is found then we will allow one retry since now we
  330. // have some previous names with no driver on CD (since it is an OEM driver)
  331. // If previous name is not found ask user to select a model
  332. //
  333. if ( !(pDriverInfo6 = Win95DriverInfo6FromName(hDevInfo,
  334. &pLocalData,
  335. pszModel,
  336. pszzPreviousNames)) ) {
  337. if ( bPreviousNamesSection ) {
  338. if ( bFirstTime == TRUE ) {
  339. ASSERT(pLocalData == NULL);
  340. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  341. hDevInfo = INVALID_HANDLE_VALUE;
  342. bFirstTime = FALSE;
  343. goto Retry;
  344. }
  345. }
  346. if ( (dwInstallFlags & DRVINST_PROMPTLESS) == 0)
  347. {
  348. PVOID pDSInfo = NULL; // Holds pointer to the driver signing class that C can't understand.
  349. HSPFILEQ CopyQueue;
  350. SP_DEVINSTALL_PARAMS DevInstallParams = {0};
  351. DevInstallParams.cbSize = sizeof(DevInstallParams);
  352. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  353. hDevInfo = CreatePrinterDeviceInfoList(hwnd);
  354. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  355. !SetDevInstallParams(hDevInfo, NULL, pszInfPath))
  356. {
  357. DWORD dwLastError;
  358. dwLastError = GetLastError();
  359. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  360. hDevInfo = INVALID_HANDLE_VALUE;
  361. SetLastError(dwLastError);
  362. goto Cleanup;
  363. }
  364. CopyQueue = SetupOpenFileQueue();
  365. if ( CopyQueue == INVALID_HANDLE_VALUE )
  366. {
  367. goto Cleanup;
  368. }
  369. //
  370. // associate the queue with the HDEVINFO
  371. //
  372. if ( SetupDiGetDeviceInstallParams(hDevInfo,
  373. NULL,
  374. &DevInstallParams) )
  375. {
  376. DevInstallParams.Flags |= DI_NOVCP;
  377. DevInstallParams.FileQueue = CopyQueue;
  378. SetupDiSetDeviceInstallParams(hDevInfo, NULL, &DevInstallParams);
  379. }
  380. if (NULL == (pDSInfo = SetupDriverSigning(hDevInfo, pszServerName, NULL,
  381. pszInfPath, PlatformWin95, 0, CopyQueue, FALSE)))
  382. {
  383. SetupCloseFileQueue(CopyQueue);
  384. goto Cleanup;
  385. }
  386. if ( BuildClassDriverList(hDevInfo) &&
  387. PSetupSelectDriver(hDevInfo) &&
  388. (pLocalData = BuildInternalData(hDevInfo, NULL)) &&
  389. ParseInf(hDevInfo, pLocalData, PlatformWin95,
  390. pszServerName, dwInstallFlags) )
  391. {
  392. LPCTSTR pDriverName;
  393. pDriverInfo6 = CloneDriverInfo6(&pLocalData->InfInfo.DriverInfo6,
  394. pLocalData->InfInfo.cbDriverInfo6);
  395. //
  396. // if setup selected a "compatible" driver:
  397. // pre-Whistler: rename the compatible driver to the requested model name
  398. // on Whistler: set the driver name to the compatible one and set the previous names section accordingly
  399. //
  400. if (IsWhistlerOrAbove(pszServerName))
  401. {
  402. pDriverName = pLocalData->DrvInfo.pszModelName;
  403. }
  404. else
  405. {
  406. pDriverName = pszModel;
  407. }
  408. if ( pDriverInfo6 && (pDriverInfo6->pName = AllocStr(pDriverName)) )
  409. {
  410. bFreeDriverName = TRUE;
  411. }
  412. }
  413. //
  414. // disassociate the queue before deleting it
  415. //
  416. DevInstallParams.Flags &= ~DI_NOVCP;
  417. DevInstallParams.FlagsEx &= ~DI_FLAGSEX_ALTPLATFORM_DRVSEARCH;
  418. DevInstallParams.FileQueue = INVALID_HANDLE_VALUE;
  419. SetupDiSetDeviceInstallParams(hDevInfo, NULL, &DevInstallParams);
  420. SetupCloseFileQueue(CopyQueue);
  421. CleanupDriverSigning(pDSInfo);
  422. }
  423. }
  424. else if (lstrcmp(pDriverInfo6->pName, pszModel))
  425. {
  426. //
  427. // if the driver was selected because of an entry in the previous names section
  428. // then on anything before Whistler we need to rename the driver to the queue driver's name
  429. //
  430. if (!IsWhistlerOrAbove(pszServerName))
  431. {
  432. if (pDriverInfo6->pName = AllocStr(pszModel) )
  433. {
  434. bFreeDriverName = TRUE;
  435. }
  436. }
  437. }
  438. if ( !pDriverInfo6 || !pDriverInfo6->pName )
  439. goto Cleanup;
  440. pDriverInfo6->pEnvironment = PlatformEnv[PlatformWin95].pszName;
  441. //
  442. // For Win95 driver pszzPreviousNames does not make sense
  443. //
  444. ASSERT(pDriverInfo6->pszzPreviousNames == NULL);
  445. if ( GetPrinterDriverDirectory((LPTSTR)pszServerName,
  446. pDriverInfo6->pEnvironment,
  447. 1,
  448. (LPBYTE)szTargetPath,
  449. sizeof(szTargetPath),
  450. &dwNeeded) &&
  451. CopyPrinterDriverFiles(pDriverInfo6,
  452. pLocalData->DrvInfo.pszInfName,
  453. pszInfPath,
  454. pszDiskName,
  455. szTargetPath,
  456. hwnd,
  457. dwInstallFlags,
  458. TRUE) &&
  459. SetPreviousNamesSection(pszServerName, pszModel,
  460. (LPCTSTR) pLocalData->DrvInfo.pszModelName) &&
  461. AddPrinterDriverUsingCorrectLevel(pszServerName,
  462. pDriverInfo6,
  463. dwAddDrvFlags)
  464. )
  465. {
  466. dwRet = ERROR_SUCCESS;
  467. }
  468. Cleanup:
  469. if (pLocalData)
  470. {
  471. DestroyLocalData(pLocalData);
  472. pLocalData = NULL;
  473. }
  474. if ( dwRet != ERROR_SUCCESS )
  475. dwRet = GetLastError();
  476. if ( hDevInfo != INVALID_HANDLE_VALUE )
  477. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  478. if ( pDriverInfo6 ) {
  479. if ( bFreeDriverName )
  480. LocalFreeMem(pDriverInfo6->pName);
  481. PSetupDestroyDriverInfo3((LPDRIVER_INFO_3)pDriverInfo6);
  482. }
  483. CleanupScratchDirectory(pszServerName, PlatformWin95);
  484. CleanupScratchDirectory(pszServerName, PlatformX86);
  485. return dwRet;
  486. }
  487. /*++
  488. Routine Name:
  489. PSetupFindMappedDriver
  490. Routine Description:
  491. Find the remapped NT printer driver name for the given driver name. If the
  492. function does not find a remapped driver, it simply returns the name that was
  493. passed in. This looks in the [Printer Driver Mapping] and
  494. [Printer Driver Mapping WINNT] sections of prtupg9x.inf.
  495. Arguments:
  496. bWinNT - If TRUE, find this from the WINNT section.
  497. pszDriverName - The driver name to be remapped.
  498. ppszRemappedDriverName - The remapped driver name, allocated and returned
  499. to the caller. (Free with PSetupFreeMem).
  500. pbDriverFound - If TRUE, the driver was remapped. Otherwise, the
  501. output is simpy a copy of the input.
  502. Return Value:
  503. If there is an unexpected error, FALSE, otherwise TRUE. Last Error has the
  504. error code.
  505. --*/
  506. BOOL
  507. PSetupFindMappedDriver(
  508. IN BOOL bWinNT,
  509. IN LPCTSTR pszDriverName,
  510. OUT LPTSTR *ppszRemappedDriverName,
  511. OUT BOOL *pbDriverFound
  512. )
  513. {
  514. HINF hInf = INVALID_HANDLE_VALUE;
  515. BOOL bRet = FALSE;
  516. BOOL bFound = FALSE;
  517. LPTSTR pszRemappedDriverName = NULL;
  518. INFCONTEXT InfContext;
  519. TCHAR szNtName[LINE_LEN];
  520. bRet = pszDriverName && ppszRemappedDriverName && pbDriverFound;
  521. if (ppszRemappedDriverName)
  522. {
  523. *ppszRemappedDriverName = NULL;
  524. }
  525. if (pbDriverFound)
  526. {
  527. *pbDriverFound = FALSE;
  528. }
  529. if (!bRet)
  530. {
  531. SetLastError(ERROR_INVALID_PARAMETER);
  532. }
  533. //
  534. // Open ntprint.inf, it should be in the %windir%\inf directory.
  535. //
  536. if (bRet)
  537. {
  538. hInf = SetupOpenInfFile(cszPrtupg9x, NULL, INF_STYLE_WIN4, NULL);
  539. bRet = hInf != INVALID_HANDLE_VALUE;
  540. }
  541. //
  542. // Find the driver in the appropriate Printer Driver Mapping section of the
  543. // inf.
  544. //
  545. if (bRet)
  546. {
  547. bFound = SetupFindFirstLine(hInf, bWinNT ? cszPrinterDriverMappingNT : cszPrinterDriverMapping, pszDriverName, &InfContext);
  548. //
  549. // Get the name of the in-box driver.
  550. //
  551. if (bFound)
  552. {
  553. bRet = SetupGetStringField(&InfContext, 1, szNtName, COUNTOF(szNtName), NULL);
  554. }
  555. else if (ERROR_LINE_NOT_FOUND != GetLastError())
  556. {
  557. bRet = FALSE;
  558. }
  559. }
  560. //
  561. // If we found the driver, return it. Otherwise, just allocate and return the
  562. // string that was passed in.
  563. //
  564. if (bRet)
  565. {
  566. if (bFound)
  567. {
  568. pszRemappedDriverName = AllocStr(szNtName);
  569. *pbDriverFound = pszRemappedDriverName != NULL;
  570. }
  571. else
  572. {
  573. //
  574. // The remapped driver is not in the inf. Return the one we were passed in.
  575. //
  576. pszRemappedDriverName = AllocStr(pszDriverName);
  577. }
  578. bRet = pszRemappedDriverName != NULL;
  579. }
  580. if (bRet)
  581. {
  582. *ppszRemappedDriverName = pszRemappedDriverName;
  583. pszRemappedDriverName = NULL;
  584. }
  585. if (hInf != INVALID_HANDLE_VALUE)
  586. {
  587. SetupCloseInfFile(hInf);
  588. }
  589. if (pszRemappedDriverName)
  590. {
  591. LocalFreeMem(pszRemappedDriverName);
  592. }
  593. return bRet;
  594. }