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.

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