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.

2259 lines
64 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Upgrade.c
  6. Abstract:
  7. Code to upgrade printer drivers during system upgrade
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 20-Dec-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include <syssetup.h>
  14. #include <regstr.h>
  15. //
  16. // Strings used in PrintUpg.inf
  17. //
  18. TCHAR cszUpgradeInf[] = TEXT("printupg.inf");
  19. TCHAR cszPrintDriverMapping[] = TEXT("Printer Driver Mapping");
  20. TCHAR cszVersion[] = TEXT("Version");
  21. TCHAR cszExcludeSection[] = TEXT("Excluded Driver Files");
  22. TCHAR cszSyssetupInf[] = TEXT("layout.inf");
  23. TCHAR cszMappingSection[] = TEXT("Printer Driver Mapping");
  24. TCHAR cszSystemServers[] = TEXT("System\\CurrentControlSet\\Control\\Print\\Providers\\LanMan Print Services\\Servers\\");
  25. TCHAR cszSystemConnections[] = TEXT("System\\CurrentControlSet\\Control\\Print\\Connections\\");
  26. TCHAR cszSoftwareServers[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Providers\\LanMan Print Services\\Servers\\");
  27. TCHAR cszSoftwarePrint[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Print");
  28. TCHAR cszBadConnections[] = TEXT("Bad Connections");
  29. TCHAR cszPrinters[] = TEXT("\\Printers\\");
  30. TCHAR cszDriver[] = TEXT("Printer Driver");
  31. TCHAR cszShareName[] = TEXT("Share Name");
  32. TCHAR cszConnections[] = TEXT("\\Printers\\Connections");
  33. TCHAR cszSetupKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Setup");
  34. TCHAR cszSourcePath[] = TEXT("SourcePath");
  35. //
  36. // What level info we wanted logged in setup log
  37. //
  38. LogSeverity gLogSeverityLevel = LogSevInformation;
  39. //
  40. // Define structure used to track printer drivers
  41. // that need to be added via AddPrinterDriver().
  42. //
  43. typedef struct _DRIVER_TO_ADD {
  44. struct _DRIVER_TO_ADD *pNext;
  45. PPSETUP_LOCAL_DATA pLocalData;
  46. PLATFORM platform;
  47. } DRIVER_TO_ADD, *PDRIVER_TO_ADD;
  48. typedef struct _DRIVER_TO_DELETE {
  49. struct _DRIVER_TO_DELETE *pNext;
  50. LPTSTR pszDriverName;
  51. LPTSTR pszNewDriverName; // In box driver to replace
  52. LPTSTR pszEnvironment;
  53. DWORD dwVersion;
  54. } DRIVER_TO_DELETE, *PDRIVER_TO_DELETE;
  55. typedef struct _CONNECTION_TO_DELETE {
  56. struct _CONNECTION_TO_DELETE *pNext;
  57. LPTSTR pszConnectionName;
  58. } CONNECTION_TO_DELETE, *PCONNECTION_TO_DELETE;
  59. //
  60. // gpDriversToAdd list will have all the drivers we are trying to upgrade
  61. //
  62. PDRIVER_TO_ADD gpDriversToAdd = NULL;
  63. PDRIVER_TO_DELETE gpBadDrvList = NULL;
  64. // Forward Reference for recursive call
  65. BOOL
  66. PruneBadConnections(
  67. IN PDRIVER_TO_DELETE pBadDrivers
  68. );
  69. VOID
  70. DeleteRegKey(
  71. IN HKEY hRegKey,
  72. IN LPTSTR pszSubKey
  73. );
  74. DWORD
  75. DeleteCache(
  76. VOID
  77. );
  78. VOID
  79. LogError(
  80. IN LogSeverity Severity,
  81. IN UINT uMessageId,
  82. ...
  83. )
  84. /*++
  85. Routine Description:
  86. Logs an error in driver upgrade. We will do driver level error logging
  87. and not file level (ie. Faile to upgrade "HP Laser Jet 4" for Alpha
  88. instead of failure on RASDDUI.DLL for Alpha)
  89. Arguments:
  90. Return Value:
  91. None.
  92. --*/
  93. {
  94. LPTSTR pszFormat;
  95. TCHAR szMsg[1024];
  96. va_list vargs;
  97. if ( Severity < gLogSeverityLevel )
  98. return;
  99. if ( pszFormat = GetStringFromRcFile(uMessageId) )
  100. {
  101. va_start(vargs, uMessageId);
  102. StringCchVPrintf(szMsg, SIZECHARS(szMsg), pszFormat, vargs);
  103. SetupLogError(szMsg, Severity);
  104. LocalFreeMem(pszFormat);
  105. }
  106. return;
  107. }
  108. VOID
  109. AddEntryToDriversToAddList(
  110. IN PPSETUP_LOCAL_DATA pLocalData,
  111. IN PLATFORM platform,
  112. IN OUT LPBOOL pbFail
  113. )
  114. {
  115. PDRIVER_TO_ADD pDriverToAdd;
  116. if ( *pbFail )
  117. return;
  118. pDriverToAdd = (PDRIVER_TO_ADD) LocalAllocMem(sizeof(DRIVER_TO_ADD));
  119. if ( !pDriverToAdd ) {
  120. *pbFail = TRUE;
  121. return;
  122. }
  123. pDriverToAdd->pLocalData = pLocalData;
  124. pDriverToAdd->platform = platform;
  125. pDriverToAdd->pNext = gpDriversToAdd;
  126. gpDriversToAdd = pDriverToAdd;
  127. }
  128. VOID
  129. FreeDriversToAddList(
  130. )
  131. /*++
  132. Routine Description:
  133. Free drivers to add list
  134. Arguments:
  135. None
  136. Return Value:
  137. None.
  138. --*/
  139. {
  140. PDRIVER_TO_ADD pCur, pNext;
  141. for ( pCur = gpDriversToAdd ; pCur ; pCur = pNext ) {
  142. pNext = pCur->pNext;
  143. DestroyLocalData(pCur->pLocalData);
  144. LocalFreeMem((PVOID)pCur);
  145. }
  146. gpDriversToAdd = NULL;
  147. }
  148. VOID
  149. AddEntryToDriversToDeleteList(
  150. IN LPTSTR pszDriverName,
  151. IN LPTSTR pszNewDriverName,
  152. IN LPTSTR pszEnvironment,
  153. IN DWORD dwVersion
  154. )
  155. {
  156. PDRIVER_TO_DELETE pDrvEntry;
  157. if ( pDrvEntry = (PDRIVER_TO_DELETE) LocalAllocMem(sizeof(DRIVER_TO_DELETE)) ) {
  158. pDrvEntry->pszDriverName = pszDriverName;
  159. pDrvEntry->pszNewDriverName = pszNewDriverName;
  160. pDrvEntry->pszEnvironment = pszEnvironment;
  161. pDrvEntry->dwVersion = dwVersion;
  162. pDrvEntry->pNext = gpBadDrvList;
  163. gpBadDrvList = pDrvEntry;
  164. }
  165. }
  166. LPTSTR
  167. ReadDigit(
  168. LPTSTR ptr,
  169. LPWORD pW
  170. )
  171. {
  172. TCHAR c;
  173. //
  174. // Skip spaces
  175. //
  176. while ( !iswdigit(c = *ptr) && c != TEXT('\0') )
  177. ++ptr;
  178. if ( c == TEXT('\0') )
  179. return NULL;
  180. //
  181. // Read field
  182. //
  183. for ( *pW = 0 ; iswdigit(c = *ptr) ; ++ptr )
  184. *pW = *pW * 10 + c - TEXT('0');
  185. return ptr;
  186. }
  187. HRESULT
  188. StringToDate(
  189. LPTSTR pszDate,
  190. SYSTEMTIME *pInfTime
  191. )
  192. {
  193. BOOL bRet = FALSE;
  194. ZeroMemory(pInfTime, sizeof(*pInfTime));
  195. bRet = (pszDate = ReadDigit(pszDate, &(pInfTime->wMonth))) &&
  196. (pszDate = ReadDigit(pszDate, &(pInfTime->wDay))) &&
  197. (pszDate = ReadDigit(pszDate, &(pInfTime->wYear)));
  198. //
  199. // Y2K compatible check
  200. //
  201. if ( bRet && pInfTime->wYear < 100 ) {
  202. ASSERT(pInfTime->wYear >= 100);
  203. if ( pInfTime->wYear < 10 )
  204. pInfTime->wYear += 2000;
  205. else
  206. pInfTime->wYear += 1900;
  207. }
  208. if(!bRet)
  209. {
  210. SetLastError(ERROR_INVALID_DATA);
  211. }
  212. return bRet? S_OK : GetLastErrorAsHResult();
  213. }
  214. BOOL
  215. FindPathOnSource(
  216. IN LPCTSTR pszFileName,
  217. IN HINF MasterInf,
  218. IN OUT LPTSTR pszPathOnSource,
  219. IN DWORD dwLen,
  220. OUT LPTSTR *ppszMediaDescription, OPTIONAL
  221. OUT LPTSTR *ppszTagFile OPTIONAL
  222. )
  223. /*++
  224. Routine Description:
  225. Find the path of a driver file for a specific platform in the installation
  226. directory
  227. Arguments:
  228. pszFileName : Name of the file to find source location
  229. MasterInf : Handle to the master inf
  230. pszPathOnSource : Pointer to string to build source path
  231. dwLen : Length of pszSourcePath
  232. ppszMediaDescription : Optionally function will return media description
  233. (caller should free memory)
  234. ppszTagFile : Optionally function will return tagfile name
  235. (caller should free memory)
  236. Return Value:
  237. TRUE on succes, FALSE on error.
  238. --*/
  239. {
  240. UINT DiskId;
  241. TCHAR szRelativePath[MAX_PATH];
  242. DWORD dwNeeded;
  243. if ( !SetupGetSourceFileLocation(
  244. MasterInf,
  245. NULL,
  246. pszFileName,
  247. &DiskId,
  248. szRelativePath,
  249. SIZECHARS(szRelativePath),
  250. &dwNeeded) ||
  251. !SetupGetSourceInfo(MasterInf,
  252. DiskId,
  253. SRCINFO_PATH,
  254. pszPathOnSource,
  255. dwLen,
  256. &dwNeeded) ||
  257. (DWORD)(lstrlen(szRelativePath) + lstrlen(pszPathOnSource) + 1) > dwLen ) {
  258. return FALSE;
  259. }
  260. StringCchCat(pszPathOnSource, dwLen, szRelativePath);
  261. if ( ppszMediaDescription ) {
  262. *ppszMediaDescription = NULL;
  263. if ( !SetupGetSourceInfo(MasterInf,
  264. DiskId,
  265. SRCINFO_DESCRIPTION,
  266. NULL,
  267. 0,
  268. &dwNeeded) ||
  269. !(*ppszMediaDescription = LocalAllocMem(dwNeeded * sizeof(TCHAR))) ||
  270. !SetupGetSourceInfo(MasterInf,
  271. DiskId,
  272. SRCINFO_DESCRIPTION,
  273. *ppszMediaDescription,
  274. dwNeeded,
  275. &dwNeeded) ) {
  276. LocalFreeMem(*ppszMediaDescription);
  277. *ppszMediaDescription = NULL;
  278. return FALSE;
  279. }
  280. }
  281. if ( ppszTagFile ) {
  282. *ppszTagFile = NULL;
  283. if ( !SetupGetSourceInfo(MasterInf,
  284. DiskId,
  285. SRCINFO_TAGFILE,
  286. NULL,
  287. 0,
  288. &dwNeeded) ||
  289. !(*ppszTagFile = LocalAllocMem(dwNeeded * sizeof(TCHAR))) ||
  290. !SetupGetSourceInfo(MasterInf,
  291. DiskId,
  292. SRCINFO_TAGFILE,
  293. *ppszTagFile,
  294. dwNeeded,
  295. &dwNeeded) ) {
  296. if ( ppszMediaDescription )
  297. {
  298. LocalFreeMem(*ppszMediaDescription);
  299. *ppszMediaDescription = NULL;
  300. }
  301. LocalFreeMem(*ppszTagFile);
  302. *ppszTagFile = NULL;
  303. return FALSE;
  304. }
  305. }
  306. return TRUE;
  307. }
  308. VOID
  309. BuildUpgradeInfoForDriver(
  310. IN LPDRIVER_INFO_2 pDriverInfo2,
  311. IN HDEVINFO hDevInfo,
  312. IN PLATFORM platform,
  313. IN HINF PrinterInf,
  314. IN HINF UpgradeInf,
  315. IN OUT HSPFILEQ CopyQueue
  316. )
  317. /*++
  318. Routine Description:
  319. Given a printer driver name and a platform add a DRIVER_TO_ADD entry
  320. in the global list of drivers to add.
  321. The routine
  322. -- parses printer inf file to findout the DriverInfo3 info
  323. Note: driver files may change between versions
  324. -- finds out location of driver files from the master inf
  325. Arguments:
  326. pDriverInfo2 - DriverInfo2 for the existing driver
  327. hDevInfo - Printer class device information list
  328. platform - Platform for which driver needs to be installed
  329. PrinterInf - Printer inf file giving driver information
  330. UpgradeInf - Upgrade inf file handle
  331. CopyQueue - Setup CopyQueue to queue the files to be copied
  332. Return Value:
  333. None. Errors will be logged
  334. --*/
  335. {
  336. BOOL bFail = FALSE;
  337. PPSETUP_LOCAL_DATA pLocalData = NULL;
  338. DWORD BlockingStatus = BSP_PRINTER_DRIVER_OK;
  339. LPTSTR pszNewDriverName = NULL;
  340. LPTSTR pszDriverNameSaved = NULL;
  341. LPTSTR pszNewDriverNameSaved= NULL;
  342. LPTSTR pszEnvironment = NULL;
  343. DWORD dwVersion = 0;
  344. if (!InfIsCompatibleDriver(pDriverInfo2->pName,
  345. pDriverInfo2->pDriverPath, // full path for main rendering driver dll
  346. pDriverInfo2->pEnvironment,
  347. UpgradeInf,
  348. &BlockingStatus,
  349. &pszNewDriverName))
  350. {
  351. goto Cleanup;
  352. }
  353. if (BSP_PRINTER_DRIVER_BLOCKED == (BlockingStatus & BSP_BLOCKING_LEVEL_MASK)) {
  354. if(FAILED(GetPrinterDriverVersion(pDriverInfo2->pDriverPath, &dwVersion, NULL)))
  355. {
  356. goto Cleanup;
  357. }
  358. pszDriverNameSaved = AllocStr(pDriverInfo2->pName);
  359. if (!pszDriverNameSaved)
  360. {
  361. goto Cleanup;
  362. }
  363. pszEnvironment = AllocStr(pDriverInfo2->pEnvironment);
  364. if (!pszEnvironment)
  365. {
  366. LocalFreeMem(pszDriverNameSaved);
  367. pszDriverNameSaved = NULL;
  368. goto Cleanup;
  369. }
  370. //
  371. // no replacement driver -> just delete the old one, do nothing else
  372. //
  373. if (!pszNewDriverName)
  374. {
  375. AddEntryToDriversToDeleteList(pszDriverNameSaved, NULL, pszEnvironment, dwVersion);
  376. goto Cleanup;
  377. }
  378. pszNewDriverNameSaved = AllocStr(pszNewDriverName);
  379. if (!pszNewDriverNameSaved) {
  380. LocalFreeMem(pszDriverNameSaved);
  381. LocalFreeMem(pszEnvironment);
  382. pszDriverNameSaved = NULL;
  383. pszEnvironment = NULL;
  384. goto Cleanup;
  385. }
  386. AddEntryToDriversToDeleteList(pszDriverNameSaved, pszNewDriverNameSaved, pszEnvironment, dwVersion);
  387. pLocalData = PSetupDriverInfoFromName(hDevInfo, pszNewDriverNameSaved);
  388. }
  389. if ( pLocalData == NULL )
  390. pLocalData = PSetupDriverInfoFromName(hDevInfo, pDriverInfo2->pName);
  391. if ( !pLocalData || !ParseInf(hDevInfo, pLocalData, platform, NULL, 0, FALSE) ) {
  392. bFail = TRUE;
  393. goto Cleanup;
  394. }
  395. if ( SetTargetDirectories(pLocalData,
  396. platform,
  397. NULL,
  398. PrinterInf,
  399. 0) &&
  400. SetupInstallFilesFromInfSection(PrinterInf,
  401. NULL,
  402. CopyQueue,
  403. pLocalData->InfInfo.pszInstallSection,
  404. NULL,
  405. 0) ) {
  406. AddEntryToDriversToAddList(pLocalData, platform, &bFail);
  407. } else
  408. bFail = TRUE;
  409. Cleanup:
  410. if (pszNewDriverName) {
  411. LocalFreeMem(pszNewDriverName);
  412. }
  413. if ( bFail ) {
  414. DestroyLocalData(pLocalData);
  415. //
  416. // Driver could be OEM so it is ok not to upgrade it
  417. //
  418. LogError(LogSevInformation, IDS_DRIVER_UPGRADE_FAILED, pDriverInfo2->pName);
  419. }
  420. }
  421. VOID
  422. BuildUpgradeInfoForPlatform(
  423. IN PLATFORM platform,
  424. IN HDEVINFO hDevInfo,
  425. IN HINF MasterInf,
  426. IN HINF PrinterInf,
  427. IN HINF UpgradeInf,
  428. IN OUT HSPFILEQ CopyQueue
  429. )
  430. /*++
  431. Routine Description:
  432. Build the printer driver upgrade information for the platform
  433. Arguments:
  434. platform - Platform id
  435. hDevInfo - Printer class device information list
  436. MasterInf - Handle to master layout.inf
  437. PrinterInf - Handle to printer inf (ntprint.inf)
  438. UpgradeInf - Handle to upgrade inf (printupg.inf)
  439. CopyQueue - Setup CopyQueue to queue the files to be copied
  440. Return Value:
  441. None. Errors will be logged
  442. --*/
  443. {
  444. DWORD dwLastError, dwNeeded, dwReturned;
  445. LPBYTE p = NULL;
  446. LPDRIVER_INFO_2 pDriverInfo2;
  447. if ( EnumPrinterDrivers(NULL,
  448. PlatformEnv[platform].pszName,
  449. 2,
  450. NULL,
  451. 0,
  452. &dwNeeded,
  453. &dwReturned) ) {
  454. //
  455. // Success no installed printer drivers for this platform
  456. //
  457. goto Cleanup;
  458. }
  459. dwLastError = GetLastError();
  460. if ( dwLastError != ERROR_INSUFFICIENT_BUFFER ) {
  461. LogError(LogSevError, IDS_UPGRADE_FAILED,
  462. TEXT("EnumPrinterDrivers"), dwLastError);
  463. goto Cleanup;
  464. }
  465. p = LocalAllocMem(dwNeeded);
  466. if ( !p ||
  467. !EnumPrinterDrivers(NULL,
  468. PlatformEnv[platform].pszName,
  469. 2,
  470. p,
  471. dwNeeded,
  472. &dwNeeded,
  473. &dwReturned) ) {
  474. LogError(LogSevError, IDS_UPGRADE_FAILED,
  475. TEXT("EnumPrinterDrivers"), dwLastError);
  476. goto Cleanup;
  477. }
  478. if ( !SetupSetPlatformPathOverride(PlatformOverride[platform].pszName) ) {
  479. LogError(LogSevError, IDS_UPGRADE_FAILED,
  480. TEXT("SetupSetPlatformPathOverride"), dwLastError);
  481. goto Cleanup;
  482. }
  483. for ( dwNeeded = 0, pDriverInfo2 = (LPDRIVER_INFO_2) p ;
  484. dwNeeded < dwReturned ;
  485. ++dwNeeded, ++pDriverInfo2 ) {
  486. //
  487. // ICM files need to be copied once only, for native architecture ..
  488. //
  489. BuildUpgradeInfoForDriver(pDriverInfo2,
  490. hDevInfo,
  491. platform,
  492. PrinterInf,
  493. UpgradeInf,
  494. CopyQueue);
  495. }
  496. Cleanup:
  497. if ( p )
  498. LocalFreeMem(p);
  499. }
  500. VOID
  501. InstallInternetPrintProvider(
  502. VOID
  503. )
  504. /*++
  505. Routine Description:
  506. Installs internet print provider on upgrade
  507. Arguments:
  508. None
  509. Return Value:
  510. None. Errors will be logged
  511. --*/
  512. {
  513. PROVIDOR_INFO_1 ProviderInfo1;
  514. ProviderInfo1.pName = TEXT("Internet Print Provider");
  515. ProviderInfo1.pEnvironment = NULL;
  516. ProviderInfo1.pDLLName = TEXT("inetpp.dll");
  517. if ( !AddPrintProvidor(NULL, 1, (LPBYTE)(&ProviderInfo1)) )
  518. LogError(LogSevError, IDS_UPGRADE_FAILED,
  519. TEXT("AddPrintProvidor"), GetLastError());
  520. return;
  521. }
  522. BOOL
  523. KeepPreviousName(
  524. IN PDRIVER_INFO_4 pEnumDrvInfo,
  525. IN DWORD dwCount,
  526. IN OUT PDRIVER_INFO_6 pCurDrvInfo
  527. )
  528. /*++
  529. Routine Description:
  530. Modifies the DRIVER_INFO_6 of a driver to upgrade to keep the previous names setting
  531. of the old driver.
  532. Arguments:
  533. PDRIVER_INFO_4 the array of DRIVER_INFO_4s of the installed drivers
  534. DWORD number of entries in the array
  535. PDRIVER_INFO_6 the DRIVER_INFO_6 structure of the driver that is going to be upgraded
  536. Return Value:
  537. TRUE if the previous names section was changed, FALSE if not
  538. --*/
  539. {
  540. PDRIVER_INFO_4 pCur;
  541. DWORD dwIndex;
  542. BOOL Changed = FALSE;
  543. //
  544. // search the current driver in the enumerated ones
  545. //
  546. for (dwIndex = 0; dwIndex < dwCount ; dwIndex++)
  547. {
  548. pCur = pEnumDrvInfo + dwIndex;
  549. if (!lstrcmp(pCur->pName, pCurDrvInfo->pName))
  550. {
  551. //
  552. // if the previous PreviousNames is not NULL/empty: set the new one to
  553. // the old one. I can do without additional buffers because I keep the
  554. // enumerated buffer around till I'm done.
  555. //
  556. if (pCur->pszzPreviousNames && *pCur->pszzPreviousNames)
  557. {
  558. pCurDrvInfo->pszzPreviousNames = pCur->pszzPreviousNames;
  559. Changed = TRUE;
  560. }
  561. break;
  562. }
  563. }
  564. return Changed;
  565. }
  566. VOID
  567. ProcessPrinterDrivers(
  568. )
  569. /*++
  570. Routine Description:
  571. Process printer drivers for upgrade
  572. Arguments:
  573. None
  574. Return Value:
  575. None. Errors will be logged
  576. --*/
  577. {
  578. PDRIVER_TO_ADD pCur, pNext;
  579. DWORD dwNeeded, dwReturned;
  580. PDRIVER_INFO_4 pEnumDrv = NULL;
  581. //
  582. // Enumerate all the installed drivers. We need that later on to check for whether a
  583. // previous names entry was set.
  584. //
  585. if ( !EnumPrinterDrivers(NULL,
  586. PlatformEnv[MyPlatform].pszName,
  587. 4,
  588. NULL,
  589. 0,
  590. &dwNeeded,
  591. &dwReturned) )
  592. {
  593. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  594. !(pEnumDrv = (PDRIVER_INFO_4) LocalAllocMem(dwNeeded)) ||
  595. !EnumPrinterDrivers(NULL,
  596. PlatformEnv[MyPlatform].pszName,
  597. 4,
  598. (LPBYTE) pEnumDrv,
  599. dwNeeded,
  600. &dwNeeded,
  601. &dwReturned) )
  602. {
  603. //
  604. // I do not want to stop the upgrade of printer drivers just because I can't
  605. // keep the previous names
  606. //
  607. if (pEnumDrv)
  608. {
  609. LocalFreeMem(pEnumDrv);
  610. pEnumDrv = NULL;
  611. dwReturned = 0;
  612. }
  613. }
  614. }
  615. for ( pCur = gpDriversToAdd ; pCur ; pCur = pNext ) {
  616. pNext = pCur->pNext;
  617. pCur->pLocalData->InfInfo.DriverInfo6.pEnvironment
  618. = PlatformEnv[pCur->platform].pszName;
  619. //
  620. // keep previous names if set
  621. //
  622. if (pEnumDrv)
  623. {
  624. KeepPreviousName(pEnumDrv, dwReturned, &pCur->pLocalData->InfInfo.DriverInfo6);
  625. }
  626. if ( !AddPrinterDriver(NULL,
  627. 6,
  628. (LPBYTE)&pCur->pLocalData->InfInfo.DriverInfo6) ||
  629. !PSetupInstallICMProfiles(NULL,
  630. pCur->pLocalData->InfInfo.pszzICMFiles) ) {
  631. LogError(LogSevWarning, IDS_DRIVER_UPGRADE_FAILED,
  632. pCur->pLocalData->InfInfo.DriverInfo6.pName);
  633. }
  634. }
  635. LocalFreeMem((PVOID) pEnumDrv);
  636. }
  637. VOID
  638. ProcessBadOEMDrivers(
  639. )
  640. /*++
  641. Routine Description:
  642. Kill the bad OEM drivers so that they do not cause problems after upgrade
  643. Arguments:
  644. Return Value:
  645. None. Errors will be logged
  646. --*/
  647. {
  648. PDRIVER_TO_DELETE pCur, pNext;
  649. PruneBadConnections( gpBadDrvList );
  650. for ( pCur = gpBadDrvList ; pCur ; pCur = pNext ) {
  651. pNext = pCur->pNext;
  652. DeletePrinterDriverEx(NULL,
  653. pCur->pszEnvironment,
  654. pCur->pszDriverName,
  655. DPD_DELETE_SPECIFIC_VERSION
  656. | DPD_DELETE_UNUSED_FILES,
  657. pCur->dwVersion);
  658. LocalFreeMem(pCur->pszDriverName);
  659. LocalFreeMem(pCur->pszNewDriverName);
  660. LocalFreeMem(pCur->pszEnvironment);
  661. LocalFreeMem(pCur);
  662. }
  663. }
  664. PPSETUP_LOCAL_DATA
  665. FindLocalDataForDriver(
  666. IN LPTSTR pszDriverName
  667. )
  668. /*++
  669. Routine Description:
  670. Given a driver name find the local data for local platform for that driver
  671. Arguments:
  672. pszDriverName : Name of the printer driver we are looking for
  673. Return Value:
  674. NULL if one is not found, otherwise pointer to PSETUP_LOCAL_DATA
  675. --*/
  676. {
  677. PDRIVER_TO_ADD pCur;
  678. for ( pCur = gpDriversToAdd ; pCur ; pCur = pCur->pNext ) {
  679. if ( pCur->platform == MyPlatform &&
  680. !lstrcmpi(pCur->pLocalData->InfInfo.DriverInfo6.pName,
  681. pszDriverName) )
  682. return pCur->pLocalData;
  683. }
  684. return NULL;
  685. }
  686. VOID
  687. ProcessPrintQueues(
  688. IN HDEVINFO hDevInfo,
  689. IN HINF PrinterInf,
  690. IN HINF MasterInf
  691. )
  692. /*++
  693. Routine Description:
  694. Process per printer upgrade for each print queue
  695. Arguments:
  696. hDevInfo - Printer class device information list
  697. MasterInf - Handle to master layout.inf
  698. PrinterInf - Handle to printer inf (ntprint.info)
  699. Return Value:
  700. None. Errors will be logged
  701. --*/
  702. {
  703. LPBYTE pBuf=NULL;
  704. DWORD dwNeeded, dwReturned, dwRet, dwDontCare;
  705. HANDLE hPrinter;
  706. LPTSTR pszDriverName;
  707. LPPRINTER_INFO_2 pPrinterInfo2;
  708. PPSETUP_LOCAL_DATA pLocalData;
  709. PRINTER_DEFAULTS PrinterDefault = {NULL, NULL, PRINTER_ALL_ACCESS};
  710. PDRIVER_TO_DELETE pDrv;
  711. //
  712. // If no printers installed return
  713. //
  714. if ( EnumPrinters(PRINTER_ENUM_LOCAL,
  715. NULL,
  716. 2,
  717. NULL,
  718. 0,
  719. &dwNeeded,
  720. &dwReturned) ) {
  721. return;
  722. }
  723. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  724. !(pBuf = LocalAllocMem(dwNeeded)) ||
  725. !EnumPrinters(PRINTER_ENUM_LOCAL,
  726. NULL,
  727. 2,
  728. pBuf,
  729. dwNeeded,
  730. &dwNeeded,
  731. &dwReturned) ) {
  732. LocalFreeMem(pBuf);
  733. LogError(LogSevError, IDS_UPGRADE_FAILED, TEXT("EnumPrinters"),
  734. GetLastError());
  735. return;
  736. }
  737. for ( pPrinterInfo2 = (LPPRINTER_INFO_2)pBuf, dwNeeded = 0 ;
  738. dwNeeded < dwReturned ;
  739. ++dwNeeded, ++pPrinterInfo2 ) {
  740. if ( !OpenPrinter(pPrinterInfo2->pPrinterName, &hPrinter, &PrinterDefault) ) {
  741. LogError(LogSevError, IDS_PRINTER_UPGRADE_FAILED,
  742. pPrinterInfo2->pPrinterName, TEXT("OpenPrinter"),
  743. GetLastError());
  744. continue;
  745. }
  746. pszDriverName = pPrinterInfo2->pDriverName;
  747. //
  748. // ISSUE-2002/03/22-mikaelho
  749. // We never check if the driver has the same environment as
  750. // the printer queue - that is LOCAL_ENVIRONMENT. This means
  751. // that we might delete the printer queue based on a bad additional
  752. // driver, rather than just deleting the additional driver.
  753. // Right now however we only enumerate drivers of local environment
  754. // so no big deal. Check NTRAID marker 2002/03/14 in this file for
  755. // more info.
  756. //
  757. //
  758. // See if this is in the bad driver list
  759. //
  760. for ( pDrv = gpBadDrvList ; pDrv ; pDrv = pDrv->pNext )
  761. if ( !lstrcmpi(pPrinterInfo2->pDriverName, pDrv->pszDriverName) )
  762. break;
  763. //
  764. // If this printer is using a bad OEM driver need to fix it
  765. //
  766. if ( pDrv ) {
  767. if ( pDrv->pszNewDriverName && *pDrv->pszNewDriverName ) {
  768. pszDriverName = pDrv->pszNewDriverName;
  769. pPrinterInfo2->pDriverName = pszDriverName;
  770. if ( SetPrinter(hPrinter, 2, (LPBYTE)pPrinterInfo2, 0) ) {
  771. LogError(LogSevWarning, IDS_DRIVER_CHANGED,
  772. pPrinterInfo2->pPrinterName);
  773. }
  774. } else {
  775. if ( DeletePrinter(hPrinter) ) {
  776. LogError(LogSevError,
  777. IDS_PRINTER_DELETED,
  778. pPrinterInfo2->pPrinterName,
  779. pPrinterInfo2->pDriverName);
  780. }
  781. ClosePrinter(hPrinter);
  782. continue; // to next printer
  783. }
  784. }
  785. pLocalData = FindLocalDataForDriver(pszDriverName);
  786. dwRet = EnumPrinterDataEx(hPrinter,
  787. TEXT("CopyFiles\\ICM"),
  788. NULL,
  789. 0,
  790. &dwDontCare,
  791. &dwDontCare);
  792. if ( pLocalData )
  793. {
  794. (VOID)SetPnPInfoForPrinter(hPrinter,
  795. NULL, // Don't set PnP id during upgrade
  796. NULL,
  797. pLocalData->DrvInfo.pszManufacturer,
  798. pLocalData->DrvInfo.pszOEMUrl);
  799. }
  800. ClosePrinter(hPrinter);
  801. //
  802. // If the CopyFiles\ICM key is already found then ICM has already
  803. // been used with this printer (i.e. we are upgrading a post NT4
  804. // machine). Then we want to leave the settings the user has chosen
  805. //
  806. if ( dwRet != ERROR_FILE_NOT_FOUND )
  807. continue;
  808. if ( pLocalData && pLocalData->InfInfo.pszzICMFiles ) {
  809. (VOID)PSetupAssociateICMProfiles(pLocalData->InfInfo.pszzICMFiles,
  810. pPrinterInfo2->pPrinterName);
  811. }
  812. }
  813. LocalFreeMem(pBuf);
  814. }
  815. VOID
  816. ClearPnpReinstallFlag(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData)
  817. {
  818. DWORD dwReturn, dwConfigFlags, cbRequiredSize, dwDataType = REG_DWORD;
  819. //
  820. // get the config flags
  821. //
  822. dwReturn = SetupDiGetDeviceRegistryProperty(hDevInfo,
  823. pDevInfoData,
  824. SPDRP_CONFIGFLAGS,
  825. &dwDataType,
  826. (PBYTE) &dwConfigFlags,
  827. sizeof(dwConfigFlags),
  828. &cbRequiredSize) ?
  829. (REG_DWORD == dwDataType ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER)
  830. : GetLastError();
  831. if ((ERROR_SUCCESS == dwReturn) && (dwConfigFlags & CONFIGFLAG_REINSTALL))
  832. {
  833. //
  834. // clear to flag to make setupapi not install this device on first boot
  835. //
  836. dwConfigFlags &= ~CONFIGFLAG_REINSTALL;
  837. dwReturn = SetupDiSetDeviceRegistryProperty(hDevInfo,
  838. pDevInfoData,
  839. SPDRP_CONFIGFLAGS,
  840. (PBYTE) &dwConfigFlags,
  841. sizeof(dwConfigFlags)) ?
  842. ERROR_SUCCESS : GetLastError();
  843. }
  844. }
  845. BOOL
  846. IsInboxInstallationRequested(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData)
  847. {
  848. SP_DEVINFO_DATA DevData = {0};
  849. DWORD IsInbox = 0;
  850. DWORD dwBufSize = sizeof(IsInbox);
  851. DWORD dwType = REG_DWORD;
  852. HKEY hKey;
  853. //
  854. // open the dev reg key and get the rank
  855. //
  856. hKey = SetupDiOpenDevRegKey(hDevInfo, pDevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
  857. if (hKey != INVALID_HANDLE_VALUE)
  858. {
  859. if (ERROR_SUCCESS != RegQueryValueEx(hKey, cszBestDriverInbox, NULL, &dwType, (LPBYTE) &IsInbox, &dwBufSize))
  860. {
  861. IsInbox = 0;
  862. }
  863. RegCloseKey(hKey);
  864. }
  865. return IsInbox ? TRUE : FALSE;
  866. }
  867. VOID
  868. ProcessPnpReinstallFlags(HDEVINFO hDevInfo)
  869. {
  870. LPBYTE pBuf = NULL;
  871. DWORD dwNeeded, dwReturned, dwDontCare;
  872. HANDLE hPrinter;
  873. LPPRINTER_INFO_2 pPrinterInfo2;
  874. PRINTER_DEFAULTS PrinterDefault = {NULL, NULL, PRINTER_ALL_ACCESS};
  875. TCHAR szDeviceInstanceId[MAX_PATH];
  876. DWORD dwType = REG_DWORD;
  877. SP_DEVINFO_DATA DevData = {0};
  878. //
  879. // If no printers installed return
  880. //
  881. if ( EnumPrinters(PRINTER_ENUM_LOCAL,
  882. NULL,
  883. 2,
  884. NULL,
  885. 0,
  886. &dwNeeded,
  887. &dwReturned) ) {
  888. return;
  889. }
  890. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  891. !(pBuf = LocalAllocMem(dwNeeded)) ||
  892. !EnumPrinters(PRINTER_ENUM_LOCAL,
  893. NULL,
  894. 2,
  895. pBuf,
  896. dwNeeded,
  897. &dwNeeded,
  898. &dwReturned) ) {
  899. LocalFreeMem(pBuf);
  900. pBuf = NULL;
  901. LogError(LogSevError, IDS_UPGRADE_FAILED, TEXT("EnumPrinters"),
  902. GetLastError());
  903. return;
  904. }
  905. for ( pPrinterInfo2 = (LPPRINTER_INFO_2)pBuf, dwNeeded = 0 ;
  906. dwNeeded < dwReturned ;
  907. ++dwNeeded, ++pPrinterInfo2 ) {
  908. if ( !OpenPrinter(pPrinterInfo2->pPrinterName, &hPrinter, &PrinterDefault) ) {
  909. LogError(LogSevError, IDS_PRINTER_UPGRADE_FAILED,
  910. pPrinterInfo2->pPrinterName, TEXT("OpenPrinter"),
  911. GetLastError());
  912. continue;
  913. }
  914. //
  915. // Get the device instance ID
  916. //
  917. if ((GetPrinterDataEx( hPrinter,
  918. cszPnPKey,
  919. cszDeviceInstanceId,
  920. &dwType,
  921. (LPBYTE) szDeviceInstanceId,
  922. sizeof(szDeviceInstanceId),
  923. &dwDontCare
  924. ) == ERROR_SUCCESS) && (dwType == REG_SZ))
  925. {
  926. DevData.cbSize = sizeof(DevData);
  927. //
  928. // get the devnode
  929. //
  930. if (SetupDiOpenDeviceInfo(hDevInfo, szDeviceInstanceId, INVALID_HANDLE_VALUE, 0, &DevData))
  931. {
  932. //
  933. // if the driver that pnp wanted to install in the first place is an IHV driver, delete the
  934. // CONFIGFLAG_REINSTALL. That information was stored during the DIF_ALLOW_INSTALL
  935. // that we fail during the first phase of GUI mode setup. We want a reinstallation
  936. // happening in case of inbox so we replace the unsigned driver with an inbox driver and
  937. // and Pnp is happy because we don't switch out drivers behind their backs.
  938. // Side effect is that drivers that require user interaction (vendor setup or
  939. // multiple Pnp matches) will require that once more after the upgrade.
  940. //
  941. if (!IsInboxInstallationRequested(hDevInfo, &DevData))
  942. {
  943. ClearPnpReinstallFlag( hDevInfo, &DevData);
  944. }
  945. }
  946. }
  947. ClosePrinter(hPrinter);
  948. }
  949. LocalFreeMem(pBuf);
  950. }
  951. BOOL
  952. OpenServerKey(
  953. OUT PHKEY phKey
  954. )
  955. {
  956. // Open the Servers Key
  957. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, cszSoftwareServers, 0,
  958. KEY_READ, phKey) )
  959. {
  960. return TRUE;
  961. }
  962. else if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, cszSystemServers, 0,
  963. KEY_READ, phKey) )
  964. {
  965. return TRUE;
  966. }
  967. else
  968. return FALSE;
  969. }
  970. BOOL
  971. OpenPrintersKey(
  972. IN DWORD dwIndex,
  973. IN HKEY hInKey,
  974. OUT LPTSTR* ppszServerName,
  975. OUT PHKEY phOutKey
  976. )
  977. {
  978. BOOL bRC = TRUE;
  979. DWORD dwSrvSize, dwSrvRC, dwPrnLen, dwPrnRC;
  980. LPTSTR pszSrvPrnKey = NULL;
  981. TCHAR szServerName[MAX_PATH+1];
  982. // If we have a current ServerName free it
  983. if ( *ppszServerName )
  984. {
  985. LocalFreeMem( *ppszServerName );
  986. *ppszServerName = NULL;
  987. }
  988. if ( *phOutKey != INVALID_HANDLE_VALUE )
  989. {
  990. RegCloseKey(*phOutKey);
  991. *phOutKey = INVALID_HANDLE_VALUE;
  992. }
  993. dwSrvSize = COUNTOF(szServerName);
  994. dwSrvRC = RegEnumKey( hInKey,
  995. dwIndex,
  996. szServerName,
  997. dwSrvSize );
  998. if ( dwSrvRC == ERROR_SUCCESS )
  999. {
  1000. // Save the ServerName to return
  1001. *ppszServerName = AllocStr( szServerName );
  1002. if (!*ppszServerName)
  1003. return FALSE;
  1004. // Now Open the Printers key under ServerName
  1005. dwPrnLen = lstrlen( szServerName ) + lstrlen( cszPrinters ) + 2;
  1006. pszSrvPrnKey = (LPTSTR) LocalAllocMem( dwPrnLen * sizeof(TCHAR) );
  1007. if ( pszSrvPrnKey )
  1008. {
  1009. // Build the next key name
  1010. StringCchCopy( pszSrvPrnKey, dwPrnLen, szServerName );
  1011. StringCchCat( pszSrvPrnKey, dwPrnLen, cszPrinters );
  1012. }
  1013. else
  1014. return FALSE;
  1015. dwPrnRC = RegOpenKeyEx( hInKey, pszSrvPrnKey, 0,
  1016. KEY_READ, phOutKey );
  1017. bRC = ( dwPrnRC == ERROR_SUCCESS );
  1018. }
  1019. else if ( dwSrvRC != ERROR_NO_MORE_ITEMS )
  1020. bRC = FALSE;
  1021. if ( pszSrvPrnKey )
  1022. LocalFreeMem( pszSrvPrnKey );
  1023. return bRC;
  1024. }
  1025. BOOL
  1026. GetConnectionInfo(
  1027. IN DWORD dwIndex,
  1028. IN HKEY hKey,
  1029. OUT LPTSTR* ppszConnectionName,
  1030. OUT LPTSTR* ppszDriverName,
  1031. OUT LPTSTR* ppszShareName
  1032. )
  1033. {
  1034. // Now enum the Connection Names
  1035. BOOL bRC = FALSE;
  1036. TCHAR szConnectionName[MAX_PATH+1];
  1037. DWORD dwConnSize, dwConnRC, dwPrinterIndex;
  1038. if ( *ppszConnectionName )
  1039. {
  1040. LocalFreeMem( *ppszConnectionName );
  1041. *ppszConnectionName = NULL;
  1042. }
  1043. if ( *ppszDriverName )
  1044. {
  1045. LocalFreeMem( *ppszDriverName );
  1046. *ppszDriverName = NULL;
  1047. }
  1048. if ( *ppszShareName )
  1049. {
  1050. LocalFreeMem( *ppszShareName );
  1051. *ppszShareName = NULL;
  1052. }
  1053. dwConnSize = COUNTOF( szConnectionName );
  1054. dwConnRC = RegEnumKey( hKey,
  1055. dwIndex,
  1056. szConnectionName,
  1057. dwConnSize );
  1058. if ( dwConnRC == ERROR_SUCCESS )
  1059. {
  1060. // Now Get the Driver Model
  1061. HKEY hConnectionKey = INVALID_HANDLE_VALUE;
  1062. // Save the COnnection Name
  1063. *ppszConnectionName = AllocStr( szConnectionName );
  1064. if (*ppszConnectionName && ( ERROR_SUCCESS == RegOpenKeyEx( hKey, szConnectionName, 0,
  1065. KEY_READ, &hConnectionKey) ))
  1066. {
  1067. DWORD dwSize, dwType, dwLastPos;
  1068. // Get the buffer size for the Driver Name
  1069. if ( ERROR_SUCCESS == RegQueryValueEx(hConnectionKey, cszDriver, NULL,
  1070. &dwType, NULL, &dwSize) )
  1071. {
  1072. *ppszDriverName = (LPTSTR) LocalAllocMem( dwSize );
  1073. if (*ppszDriverName)
  1074. {
  1075. dwLastPos = (dwSize/sizeof(TCHAR)) - 1;
  1076. if ( ( ERROR_SUCCESS == RegQueryValueEx(hConnectionKey, cszDriver, NULL,
  1077. &dwType, (LPBYTE) *ppszDriverName,
  1078. &dwSize) ) )
  1079. {
  1080. bRC = TRUE;
  1081. }
  1082. (*ppszDriverName)[dwLastPos] = TEXT('\0');
  1083. }
  1084. }
  1085. // Get the buffer size for the Share Name
  1086. if ( bRC && ( ERROR_SUCCESS == RegQueryValueEx( hConnectionKey, cszShareName, NULL,
  1087. &dwType, NULL, &dwSize) ) )
  1088. {
  1089. *ppszShareName = (LPTSTR) LocalAllocMem( dwSize );
  1090. if (*ppszShareName)
  1091. {
  1092. dwLastPos = (dwSize/sizeof(TCHAR)) - 1;
  1093. if ( ( ERROR_SUCCESS != RegQueryValueEx(hConnectionKey, cszShareName, NULL,
  1094. &dwType, (LPBYTE) *ppszShareName,
  1095. &dwSize) ) )
  1096. {
  1097. bRC = FALSE;
  1098. }
  1099. (*ppszShareName)[dwLastPos] = TEXT('\0');
  1100. }
  1101. else
  1102. {
  1103. bRC = FALSE;
  1104. }
  1105. }
  1106. else
  1107. {
  1108. bRC = FALSE;
  1109. }
  1110. RegCloseKey( hConnectionKey );
  1111. }
  1112. }
  1113. else if ( dwConnRC == ERROR_NO_MORE_ITEMS )
  1114. {
  1115. bRC = TRUE;
  1116. }
  1117. return bRC;
  1118. }
  1119. BOOL
  1120. IsDriverBad(
  1121. IN LPTSTR pszDriverName,
  1122. IN PDRIVER_TO_DELETE pCurBadDriver
  1123. )
  1124. {
  1125. BOOL bFound = FALSE;
  1126. while ( !bFound && pCurBadDriver )
  1127. {
  1128. //
  1129. // The function is called to determine if a printer connection is using a
  1130. // bad driver and since the client side only has printer driver for the
  1131. // local environment we only have to check this.
  1132. //
  1133. if ( !lstrcmpi( pszDriverName, pCurBadDriver->pszDriverName ) &&
  1134. !lstrcmpi( LOCAL_ENVIRONMENT, pCurBadDriver->pszEnvironment) )
  1135. bFound = TRUE;
  1136. else
  1137. pCurBadDriver = pCurBadDriver->pNext;
  1138. }
  1139. return bFound;
  1140. }
  1141. VOID
  1142. AddToBadConnList(
  1143. IN LPTSTR pszServerName,
  1144. IN LPTSTR pszConnectionName,
  1145. OUT PCONNECTION_TO_DELETE *ppBadConnections
  1146. )
  1147. {
  1148. // Allocate space for the Struct & String
  1149. DWORD dwAllocSize, dwStrLen;
  1150. LPTSTR pszSrvConn;
  1151. PCONNECTION_TO_DELETE pBadConn;
  1152. dwStrLen = lstrlen(pszServerName) + lstrlen(pszConnectionName) + 4;
  1153. dwAllocSize = sizeof(CONNECTION_TO_DELETE) + ( dwStrLen * sizeof(TCHAR) );
  1154. pBadConn = (PCONNECTION_TO_DELETE) LocalAllocMem( dwAllocSize );
  1155. if ( pBadConn )
  1156. {
  1157. pszSrvConn = (LPTSTR) (pBadConn+1);
  1158. StringCbCopy( pszSrvConn, dwAllocSize-sizeof(CONNECTION_TO_DELETE), TEXT(",,") );
  1159. StringCbCat( pszSrvConn, dwAllocSize-sizeof(CONNECTION_TO_DELETE), pszServerName );
  1160. StringCbCat( pszSrvConn, dwAllocSize-sizeof(CONNECTION_TO_DELETE), TEXT(",") );
  1161. StringCbCat( pszSrvConn, dwAllocSize-sizeof(CONNECTION_TO_DELETE), pszConnectionName );
  1162. pBadConn->pszConnectionName = pszSrvConn;
  1163. pBadConn->pNext = *ppBadConnections;
  1164. *ppBadConnections = pBadConn;
  1165. }
  1166. }
  1167. VOID
  1168. DeleteSubKeys(
  1169. IN HKEY hRegKey
  1170. )
  1171. {
  1172. BOOL bContinue = TRUE;
  1173. DWORD dwIndex, dwSize, dwRC;
  1174. TCHAR szSubKeyName[MAX_PATH];
  1175. dwIndex = 0;
  1176. do
  1177. {
  1178. dwSize = COUNTOF(szSubKeyName);
  1179. dwRC = RegEnumKey( hRegKey,
  1180. dwIndex,
  1181. szSubKeyName,
  1182. dwSize );
  1183. if ( dwRC == ERROR_SUCCESS )
  1184. DeleteRegKey( hRegKey, szSubKeyName );
  1185. else if ( dwRC != ERROR_NO_MORE_ITEMS )
  1186. bContinue = FALSE;
  1187. }
  1188. while ( bContinue && ( dwRC != ERROR_NO_MORE_ITEMS ) );
  1189. }
  1190. VOID
  1191. DeleteRegKey(
  1192. IN HKEY hRegKey,
  1193. IN LPTSTR pszSubKey
  1194. )
  1195. {
  1196. HKEY hSubKey;
  1197. // First Open the SubKey
  1198. if ( ERROR_SUCCESS == RegOpenKeyEx(hRegKey,
  1199. pszSubKey,
  1200. 0,
  1201. KEY_READ,
  1202. &hSubKey) )
  1203. {
  1204. DeleteSubKeys( hSubKey );
  1205. RegCloseKey( hSubKey );
  1206. }
  1207. RegDeleteKey( hRegKey, pszSubKey );
  1208. }
  1209. VOID
  1210. WriteBadConnsToReg(
  1211. IN PCONNECTION_TO_DELETE pBadConnections
  1212. )
  1213. {
  1214. // First Figure out how big a buffer is neeeded to hold all Connections
  1215. PCONNECTION_TO_DELETE pCurConnection = pBadConnections;
  1216. DWORD dwSize = 0, dwError;
  1217. LPTSTR pszAllConnections = NULL,
  1218. pszCurBuf = NULL,
  1219. pszEndBuf = NULL;
  1220. HKEY hKey = INVALID_HANDLE_VALUE;
  1221. if ( !pBadConnections )
  1222. return;
  1223. while ( pCurConnection )
  1224. {
  1225. dwSize += lstrlen( pCurConnection->pszConnectionName ) + 1;
  1226. pCurConnection = pCurConnection->pNext;
  1227. }
  1228. dwSize++; // Add one for the Last NULL
  1229. pszAllConnections = LocalAllocMem( dwSize * sizeof(TCHAR) );
  1230. if ( pszAllConnections)
  1231. {
  1232. pszCurBuf = pszAllConnections;
  1233. *pszCurBuf = 0x00;
  1234. pszEndBuf = pszAllConnections + dwSize;
  1235. pCurConnection = pBadConnections;
  1236. while ( pCurConnection && ( pszCurBuf < pszEndBuf ) )
  1237. {
  1238. // Copy the Current Connection Name
  1239. StringCchCopy( pszCurBuf, dwSize - (pszCurBuf - pszAllConnections), pCurConnection->pszConnectionName );
  1240. pszCurBuf += lstrlen( pCurConnection->pszConnectionName );
  1241. pszCurBuf++;
  1242. pCurConnection = pCurConnection->pNext;
  1243. }
  1244. *pszCurBuf = 0x00;
  1245. // Open the Registry Software\Print Key
  1246. dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, cszSoftwarePrint, 0,
  1247. KEY_SET_VALUE, &hKey);
  1248. if ( dwError == ERROR_SUCCESS )
  1249. {
  1250. RegSetValueEx( hKey, cszBadConnections, 0, REG_MULTI_SZ,
  1251. (LPBYTE) pszAllConnections, ( dwSize * sizeof(TCHAR) ) );
  1252. }
  1253. }
  1254. if ( pszAllConnections )
  1255. LocalFreeMem( pszAllConnections );
  1256. if ( hKey != INVALID_HANDLE_VALUE )
  1257. RegCloseKey( hKey );
  1258. }
  1259. BOOL
  1260. FindAndPruneBadConnections(
  1261. IN PDRIVER_TO_DELETE pBadDrivers,
  1262. OUT PCONNECTION_TO_DELETE *ppBadConnections
  1263. )
  1264. {
  1265. BOOL bRC = FALSE;
  1266. HKEY hServerKey = INVALID_HANDLE_VALUE,
  1267. hPrinterKey = INVALID_HANDLE_VALUE;
  1268. DWORD dwServerIndex, dwPrinterIndex;
  1269. LPTSTR pszServerName = NULL,
  1270. pszConnectionName = NULL,
  1271. pszDriverName = NULL,
  1272. pszShareName = NULL;
  1273. // Open the Server Key
  1274. if ( !OpenServerKey( &hServerKey ) )
  1275. goto Cleanup;
  1276. dwServerIndex = 0;
  1277. do
  1278. {
  1279. // Open Printers Key for the new Server and get Server Name
  1280. if ( !OpenPrintersKey( dwServerIndex++, hServerKey, &pszServerName, &hPrinterKey ) )
  1281. goto Cleanup;
  1282. if ( !pszServerName )
  1283. break;
  1284. dwPrinterIndex = 0;
  1285. do
  1286. {
  1287. if ( !GetConnectionInfo( dwPrinterIndex++, hPrinterKey,
  1288. &pszConnectionName, &pszDriverName, &pszShareName ) )
  1289. goto Cleanup;
  1290. if ( !pszConnectionName )
  1291. break;
  1292. if( !pszDriverName || !pszShareName)
  1293. {
  1294. continue;
  1295. }
  1296. // Check if this is a bad driver
  1297. if ( IsDriverBad( pszDriverName, pBadDrivers ) )
  1298. {
  1299. AddToBadConnList( pszServerName, pszConnectionName, ppBadConnections );
  1300. AddToBadConnList( pszServerName, pszShareName, ppBadConnections );
  1301. DeleteRegKey( hPrinterKey, pszConnectionName );
  1302. dwPrinterIndex--;
  1303. LogError( LogSevError, IDS_CONNECTION_DELETED, pszConnectionName,
  1304. pszServerName, pszDriverName );
  1305. }
  1306. }
  1307. while ( pszConnectionName );
  1308. }
  1309. while ( pszServerName );
  1310. // Write all the bad connections to the Registry
  1311. WriteBadConnsToReg( *ppBadConnections );
  1312. bRC = TRUE;
  1313. Cleanup:
  1314. if ( hServerKey != INVALID_HANDLE_VALUE )
  1315. RegCloseKey(hServerKey);
  1316. if ( hPrinterKey != INVALID_HANDLE_VALUE )
  1317. RegCloseKey(hPrinterKey);
  1318. if ( pszServerName )
  1319. LocalFreeMem( pszServerName );
  1320. if ( pszConnectionName )
  1321. LocalFreeMem( pszConnectionName );
  1322. if ( pszDriverName )
  1323. LocalFreeMem( pszDriverName );
  1324. if ( pszShareName )
  1325. LocalFreeMem( pszShareName );
  1326. return bRC;
  1327. }
  1328. BOOL
  1329. GetUserConnectionKey(
  1330. IN DWORD dwIndex,
  1331. OUT PHKEY phKey
  1332. )
  1333. {
  1334. DWORD dwSize, dwRC, dwConnRC;
  1335. TCHAR szUserKey[MAX_PATH];
  1336. DWORD dwConnLen;
  1337. LPTSTR pszConnKey;
  1338. if ( *phKey != INVALID_HANDLE_VALUE )
  1339. {
  1340. RegCloseKey(*phKey);
  1341. *phKey = INVALID_HANDLE_VALUE;
  1342. }
  1343. dwSize = COUNTOF(szUserKey);
  1344. dwRC = RegEnumKey( HKEY_USERS,
  1345. dwIndex,
  1346. szUserKey,
  1347. dwSize );
  1348. if ( dwRC == ERROR_SUCCESS )
  1349. {
  1350. // Open Connections Key for this user
  1351. dwConnLen = lstrlen( szUserKey ) + lstrlen( cszConnections ) + 3;
  1352. pszConnKey = (LPTSTR) LocalAllocMem( dwConnLen * sizeof(TCHAR) );
  1353. if ( pszConnKey )
  1354. {
  1355. // Build the next key name
  1356. StringCchCopy( pszConnKey, dwConnLen, szUserKey );
  1357. StringCchCat( pszConnKey, dwConnLen, cszConnections );
  1358. }
  1359. else
  1360. return FALSE;
  1361. dwConnRC = RegOpenKeyEx( HKEY_USERS, pszConnKey, 0, KEY_READ, phKey );
  1362. if (dwConnRC != ERROR_SUCCESS)
  1363. *phKey = INVALID_HANDLE_VALUE;
  1364. }
  1365. else
  1366. return FALSE;
  1367. if ( pszConnKey )
  1368. LocalFreeMem( pszConnKey );
  1369. return TRUE;
  1370. }
  1371. VOID
  1372. GetMachineConnectionKey(
  1373. OUT PHKEY phKey
  1374. )
  1375. {
  1376. *phKey = INVALID_HANDLE_VALUE;
  1377. //
  1378. // Open the Machine Connections Key. These can only be added by
  1379. // AddPerMachineConnection.
  1380. //
  1381. if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, cszSystemConnections, 0,
  1382. KEY_READ, phKey))
  1383. {
  1384. *phKey = INVALID_HANDLE_VALUE;
  1385. }
  1386. }
  1387. BOOL
  1388. GetNextConnection(
  1389. IN DWORD dwIndex,
  1390. IN HKEY hKey,
  1391. OUT LPTSTR* ppszConnectionName
  1392. )
  1393. {
  1394. // Enum Connection Names
  1395. TCHAR szConnectionName[MAX_PATH];
  1396. DWORD dwConnSize, dwConnRC;
  1397. if ( *ppszConnectionName )
  1398. {
  1399. LocalFreeMem( *ppszConnectionName );
  1400. *ppszConnectionName = NULL;
  1401. }
  1402. dwConnSize = COUNTOF( szConnectionName );
  1403. dwConnRC = RegEnumKey( hKey,
  1404. dwIndex++,
  1405. szConnectionName,
  1406. dwConnSize );
  1407. if ( dwConnRC == ERROR_SUCCESS )
  1408. {
  1409. // Save the Connection Name
  1410. *ppszConnectionName = AllocStr( szConnectionName );
  1411. if ( !*ppszConnectionName )
  1412. return FALSE;
  1413. }
  1414. else if ( dwConnRC != ERROR_NO_MORE_ITEMS )
  1415. return FALSE;
  1416. return TRUE;
  1417. }
  1418. BOOL
  1419. IsConnectionBad(
  1420. IN LPTSTR pszConnectionName,
  1421. IN PCONNECTION_TO_DELETE pCurBadConn
  1422. )
  1423. {
  1424. BOOL bFound = FALSE;
  1425. while ( !bFound && pCurBadConn )
  1426. {
  1427. if ( !lstrcmpi( pszConnectionName, pCurBadConn->pszConnectionName ) )
  1428. bFound = TRUE;
  1429. else
  1430. pCurBadConn = pCurBadConn->pNext;
  1431. }
  1432. return bFound;
  1433. }
  1434. BOOL
  1435. PruneUserOrMachineEntries(
  1436. IN PCONNECTION_TO_DELETE pBadConnections,
  1437. IN BOOL bPruneUsers
  1438. )
  1439. {
  1440. BOOL bRC = FALSE, bMoreUsers;
  1441. DWORD dwUserIndex = 0;
  1442. HKEY hConnectionKey = INVALID_HANDLE_VALUE;
  1443. LPTSTR pszConnectionName = NULL;
  1444. DWORD dwConnectionIndex;
  1445. do
  1446. {
  1447. if ( bPruneUsers)
  1448. bMoreUsers = GetUserConnectionKey( dwUserIndex++, &hConnectionKey );
  1449. else
  1450. {
  1451. GetMachineConnectionKey( &hConnectionKey );
  1452. bMoreUsers = FALSE;
  1453. }
  1454. if ( hConnectionKey == INVALID_HANDLE_VALUE )
  1455. continue;
  1456. dwConnectionIndex = 0;
  1457. do
  1458. {
  1459. if ( !GetNextConnection( dwConnectionIndex++, hConnectionKey, &pszConnectionName ) )
  1460. goto Cleanup;
  1461. if ( pszConnectionName && IsConnectionBad( pszConnectionName, pBadConnections ) )
  1462. {
  1463. DeleteRegKey( hConnectionKey, pszConnectionName );
  1464. dwConnectionIndex--;
  1465. }
  1466. }
  1467. while ( pszConnectionName );
  1468. }
  1469. while ( bMoreUsers );
  1470. bRC = TRUE;
  1471. Cleanup:
  1472. if ( hConnectionKey != INVALID_HANDLE_VALUE )
  1473. RegCloseKey( hConnectionKey );
  1474. if ( pszConnectionName )
  1475. LocalFreeMem( pszConnectionName );
  1476. return bRC;
  1477. }
  1478. VOID
  1479. ClearConnList(
  1480. IN PCONNECTION_TO_DELETE pCurBadConn
  1481. )
  1482. {
  1483. PCONNECTION_TO_DELETE pNextBadConn;
  1484. while (pCurBadConn)
  1485. {
  1486. pNextBadConn = pCurBadConn->pNext;
  1487. LocalFreeMem( pCurBadConn );
  1488. pCurBadConn = pNextBadConn;
  1489. }
  1490. }
  1491. BOOL
  1492. PruneBadConnections(
  1493. IN PDRIVER_TO_DELETE pBadDrivers
  1494. )
  1495. {
  1496. BOOL bRC;
  1497. PCONNECTION_TO_DELETE pBadConnections = NULL;
  1498. bRC = FindAndPruneBadConnections( pBadDrivers, &pBadConnections );
  1499. //
  1500. // ISSUE-2002/03/15-mikaelho
  1501. // The first call is useless since we won't be able to access
  1502. // data from HKEY_USERS at this point!
  1503. //
  1504. if ( bRC )
  1505. bRC = PruneUserOrMachineEntries( pBadConnections, TRUE );
  1506. if ( bRC )
  1507. bRC = PruneUserOrMachineEntries( pBadConnections, FALSE );
  1508. ClearConnList( pBadConnections );
  1509. return( bRC );
  1510. }
  1511. DWORD
  1512. NtPrintUpgradePrinters(
  1513. IN HWND WindowToDisable,
  1514. IN PCINTERNAL_SETUP_DATA pSetupData
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. Routine called by setup to upgrade printer drivers.
  1519. Setup calls this routine after putting up a billboard saying something like
  1520. "Upgrading printer drivers" ...
  1521. The function kills all the bad OEM drivers so that they do not cause problems
  1522. after upgrade as well as removing bad point and print connections. The function
  1523. first enumerates all bad drivers on a machine. Then it sets a registry key
  1524. HKLM\Software\\Microsoft\Windows NT\CurrentVersion\Print\Bad Connections that
  1525. is used e.g. by PSetupKillBadUserConnections so that all bad point-and-print
  1526. connections are removed. Finally it removes all the bad printer drivers.
  1527. Arguments:
  1528. WindowToDisable : supplies window handle of current top-level window
  1529. pSetupData : Pointer to INTERNAL_SETUP_DATA
  1530. Return Value:
  1531. ERROR_SUCCESS on success, else Win32 error code
  1532. None.
  1533. --*/
  1534. {
  1535. HINF MasterInf = INVALID_HANDLE_VALUE,
  1536. PrinterInf = INVALID_HANDLE_VALUE,
  1537. UpgradeInf = INVALID_HANDLE_VALUE;
  1538. PVOID QueueContext = NULL;
  1539. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  1540. DWORD dwLastError = ERROR_SUCCESS, dwNeeded;
  1541. HSPFILEQ CopyQueue;
  1542. BOOL bRet = FALSE, bColor = FALSE;
  1543. LPCTSTR pszInstallationSource;
  1544. TCHAR szColorDir[MAX_PATH];
  1545. if ( !pSetupData )
  1546. return ERROR_INVALID_PARAMETER;
  1547. InstallInternetPrintProvider();
  1548. pszInstallationSource = (LPCTSTR)pSetupData->SourcePath; //ANSI wont work
  1549. //
  1550. // Create a setup file copy queue.
  1551. //
  1552. CopyQueue = SetupOpenFileQueue();
  1553. if ( CopyQueue == INVALID_HANDLE_VALUE ) {
  1554. LogError(LogSevError, IDS_UPGRADE_FAILED,
  1555. TEXT("SetupOpenFileQueue"), GetLastError());
  1556. goto Cleanup;
  1557. }
  1558. //
  1559. // Open ntprint.inf -- all the printer drivers shipped with NT should
  1560. // be in ntprint.inf
  1561. //
  1562. PrinterInf = SetupOpenInfFile(cszNtprintInf, NULL, INF_STYLE_WIN4, NULL);
  1563. MasterInf = SetupOpenInfFile(cszSyssetupInf, NULL, INF_STYLE_WIN4, NULL);
  1564. UpgradeInf = SetupOpenInfFile(cszUpgradeInf, NULL, INF_STYLE_WIN4, NULL);
  1565. if ( PrinterInf == INVALID_HANDLE_VALUE ||
  1566. MasterInf == INVALID_HANDLE_VALUE ||
  1567. UpgradeInf == INVALID_HANDLE_VALUE ) {
  1568. LogError(LogSevError, IDS_UPGRADE_FAILED,
  1569. TEXT("SetupOpenInfFile"), GetLastError());
  1570. goto Cleanup;
  1571. }
  1572. //
  1573. // Build printer driver class list
  1574. //
  1575. hDevInfo = CreatePrinterDeviceInfoList(WindowToDisable);
  1576. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  1577. !PSetupBuildDriversFromPath(hDevInfo, cszNtprintInf, TRUE) ) {
  1578. LogError(LogSevError, IDS_UPGRADE_FAILED,
  1579. TEXT("Building driver list"), GetLastError());
  1580. goto Cleanup;
  1581. }
  1582. ProcessPnpReinstallFlags(hDevInfo);
  1583. dwNeeded = sizeof(szColorDir);
  1584. bColor = GetColorDirectory(NULL, szColorDir, &dwNeeded);
  1585. //
  1586. // NTRAID#NTBUG9-577488-2002/03/14-mikaelho
  1587. // MyPlatform is hard coded so we will e.g. not delete a bad x86 driver on
  1588. // an IA64 machine during upgrades!
  1589. // All calls to EnumPrinterDrivers must be modified.
  1590. //
  1591. BuildUpgradeInfoForPlatform(MyPlatform,
  1592. hDevInfo,
  1593. MasterInf,
  1594. PrinterInf,
  1595. UpgradeInf,
  1596. CopyQueue);
  1597. //
  1598. // If no printer drivers to upgrade we are done
  1599. //
  1600. if ( !gpDriversToAdd && !gpBadDrvList ) {
  1601. bRet = TRUE;
  1602. goto Cleanup;
  1603. }
  1604. //
  1605. // Copy the printer driver files over
  1606. //
  1607. if ( gpDriversToAdd )
  1608. {
  1609. QueueContext = SetupInitDefaultQueueCallbackEx( WindowToDisable, INVALID_HANDLE_VALUE, 0, 0, NULL );
  1610. if ( !QueueContext ) {
  1611. LogError(LogSevError, IDS_UPGRADE_FAILED,
  1612. TEXT("SetupInitDefaultQueue"), GetLastError());
  1613. goto Cleanup;
  1614. }
  1615. if ( !SetupCommitFileQueue(WindowToDisable,
  1616. CopyQueue,
  1617. SetupDefaultQueueCallback,
  1618. QueueContext) ) {
  1619. LogError(LogSevError, IDS_UPGRADE_FAILED,
  1620. TEXT("SetupCommitFileQueue"), GetLastError());
  1621. goto Cleanup;
  1622. }
  1623. ProcessPrinterDrivers();
  1624. }
  1625. ProcessPrintQueues(hDevInfo, PrinterInf, MasterInf);
  1626. FreeDriversToAddList();
  1627. ProcessBadOEMDrivers();
  1628. bRet = TRUE;
  1629. Cleanup:
  1630. if ( !bRet )
  1631. dwLastError = GetLastError();
  1632. if ( QueueContext )
  1633. SetupTermDefaultQueueCallback(QueueContext);
  1634. if ( CopyQueue != INVALID_HANDLE_VALUE )
  1635. SetupCloseFileQueue(CopyQueue);
  1636. if ( PrinterInf != INVALID_HANDLE_VALUE )
  1637. SetupCloseInfFile(PrinterInf);
  1638. if ( MasterInf != INVALID_HANDLE_VALUE )
  1639. SetupCloseInfFile(MasterInf);
  1640. if ( UpgradeInf != INVALID_HANDLE_VALUE )
  1641. SetupCloseInfFile(UpgradeInf);
  1642. if ( hDevInfo != INVALID_HANDLE_VALUE )
  1643. DestroyOnlyPrinterDeviceInfoList(hDevInfo);
  1644. CleanupScratchDirectory(NULL, PlatformAlpha);
  1645. CleanupScratchDirectory(NULL, PlatformX86);
  1646. CleanupScratchDirectory(NULL, PlatformMIPS);
  1647. CleanupScratchDirectory(NULL, PlatformPPC);
  1648. CleanupScratchDirectory(NULL, PlatformWin95);
  1649. CleanupScratchDirectory(NULL, PlatformIA64);
  1650. CleanupScratchDirectory(NULL, PlatformAlpha64);
  1651. // Cleanup the Connection Cache
  1652. DeleteCache();
  1653. (VOID) SetupSetPlatformPathOverride(NULL);
  1654. return dwLastError;
  1655. }
  1656. /*++
  1657. Routine Name
  1658. DeleteSubkeys
  1659. Routine Description:
  1660. Deletes the subtree of a key in registry.
  1661. The key and ites values remeain, only subkeys are deleted
  1662. Arguments:
  1663. hKey - handle to the key
  1664. Return Value:
  1665. Error code of the operation
  1666. --*/
  1667. DWORD
  1668. DeleteSubkeys(
  1669. HKEY hKey
  1670. )
  1671. {
  1672. DWORD cchData;
  1673. TCHAR SubkeyName[MAX_PATH];
  1674. HKEY hSubkey;
  1675. LONG Status;
  1676. FILETIME ft;
  1677. cchData = SIZECHARS(SubkeyName);
  1678. while ( ( Status = RegEnumKeyEx( hKey, 0, SubkeyName, &cchData,
  1679. NULL, NULL, NULL, &ft ) ) == ERROR_SUCCESS )
  1680. {
  1681. Status = RegCreateKeyEx(hKey, SubkeyName, 0, NULL, 0,
  1682. KEY_READ, NULL, &hSubkey, NULL );
  1683. if (Status == ERROR_SUCCESS)
  1684. {
  1685. Status = DeleteSubkeys(hSubkey);
  1686. RegCloseKey(hSubkey);
  1687. if (Status == ERROR_SUCCESS)
  1688. RegDeleteKey(hKey, SubkeyName);
  1689. }
  1690. //
  1691. // N.B. Don't increment since we've deleted the zeroth item.
  1692. //
  1693. cchData = SIZECHARS(SubkeyName);
  1694. }
  1695. if( Status == ERROR_NO_MORE_ITEMS)
  1696. Status = ERROR_SUCCESS;
  1697. return Status;
  1698. }
  1699. /*++
  1700. Routine Name
  1701. RemoveRegKey
  1702. Routine Description:
  1703. Deletes the subtree of a key in registry.
  1704. The key and ites values remeain, only subkeys are deleted
  1705. Arguments:
  1706. pszKey - location of the key in registry
  1707. Ex: "\\Software\\Microsoft"
  1708. Return Value:
  1709. Error code of the operation
  1710. --*/
  1711. DWORD
  1712. RemoveRegKey(
  1713. IN LPTSTR pszKey
  1714. )
  1715. {
  1716. DWORD LastError;
  1717. HKEY hRootKey;
  1718. LastError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0,
  1719. KEY_READ, &hRootKey);
  1720. if (LastError != ERROR_SUCCESS)
  1721. {
  1722. DBGMSG( DBG_TRACE, ("RemoveRegKey RegOpenKeyEx Error %d\n", LastError));
  1723. }
  1724. else
  1725. {
  1726. LastError = DeleteSubkeys(hRootKey);
  1727. RegCloseKey(hRootKey);
  1728. }
  1729. return LastError;
  1730. }
  1731. /*++
  1732. Routine Name
  1733. DeleteCache
  1734. Routine Description:
  1735. Deletes the printer connection cache, including the old location in Registry
  1736. Arguments:
  1737. None
  1738. Return Value:
  1739. Error code of the operation
  1740. --*/
  1741. DWORD
  1742. DeleteCache(
  1743. VOID
  1744. )
  1745. {
  1746. DWORD LastError;
  1747. LPTSTR pszRegWin32Root = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Providers\\LanMan Print Services\\Servers");
  1748. LPTSTR pszPrevWin32CacheLocation = TEXT("System\\CurrentControlSet\\Control\\Print\\Providers\\LanMan Print Services\\Servers");
  1749. LastError = RemoveRegKey(pszPrevWin32CacheLocation);
  1750. LastError = RemoveRegKey(pszRegWin32Root);
  1751. return LastError;
  1752. }
  1753. VOID
  1754. GetBadConnsFromReg(
  1755. IN PCONNECTION_TO_DELETE *ppBadConnections
  1756. )
  1757. {
  1758. // Open the Key in the User Space
  1759. // First Figure out how big a buffer is neeeded to hold all Connections
  1760. PCONNECTION_TO_DELETE pCurConnection;
  1761. DWORD dwSize, dwError, dwType, dwLastPos;
  1762. LPTSTR pszAllConnections = NULL,
  1763. pszCurBuf = NULL,
  1764. pszEndBuf = NULL;
  1765. HKEY hKey = INVALID_HANDLE_VALUE;
  1766. // Open the Registry Software\Print Key
  1767. dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, cszSoftwarePrint, 0,
  1768. KEY_READ, &hKey);
  1769. if ( dwError != ERROR_SUCCESS )
  1770. return;
  1771. // Get the buffer size for the Share Name
  1772. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, cszBadConnections, NULL,
  1773. &dwType, NULL, &dwSize) )
  1774. {
  1775. pszAllConnections = (LPTSTR) LocalAllocMem( dwSize );
  1776. dwLastPos = (dwSize/sizeof(TCHAR)) - 1;
  1777. if ( pszAllConnections &&
  1778. (dwLastPos > 0) &&
  1779. ( ERROR_SUCCESS == RegQueryValueEx(hKey, cszBadConnections, NULL,
  1780. &dwType, (LPBYTE) pszAllConnections,
  1781. &dwSize) ) )
  1782. {
  1783. // Build all the Bad Connection structures
  1784. DWORD dwAllocSize, dwStrLen;
  1785. PCONNECTION_TO_DELETE pBadConn;
  1786. pszAllConnections[dwLastPos-1] = TEXT('\0');
  1787. pszAllConnections[dwLastPos] = TEXT('\0');
  1788. pszCurBuf = pszAllConnections;
  1789. while ( ( dwStrLen = lstrlen(pszCurBuf) ) > 0 )
  1790. {
  1791. dwAllocSize = sizeof(CONNECTION_TO_DELETE) + ( (dwStrLen+1) * sizeof(TCHAR) );
  1792. pBadConn = (PCONNECTION_TO_DELETE) LocalAllocMem( dwAllocSize );
  1793. if ( pBadConn )
  1794. {
  1795. pBadConn->pszConnectionName = (LPTSTR) (pBadConn+1);
  1796. StringCbCopy( pBadConn->pszConnectionName, dwAllocSize-sizeof(CONNECTION_TO_DELETE), pszCurBuf );
  1797. pBadConn->pNext = *ppBadConnections;
  1798. *ppBadConnections = pBadConn;
  1799. }
  1800. else
  1801. break;
  1802. pszCurBuf += dwStrLen + 1;
  1803. }
  1804. }
  1805. }
  1806. // Free up the Allocated Mem
  1807. if ( pszAllConnections )
  1808. LocalFreeMem( pszAllConnections );
  1809. if ( hKey != INVALID_HANDLE_VALUE )
  1810. RegCloseKey( hKey );
  1811. }
  1812. VOID
  1813. PSetupKillBadUserConnections(
  1814. VOID
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. Removes a user's bad Point-and-Print connections. The function is called
  1819. as each user logs on after setup completes. It read the registry value
  1820. HKLM\Software\Microsoft\Windows NT\CurrentVersion\Print\Bad Connections
  1821. to find the bad connection. This registry value is set by the function
  1822. NtPrintUpgradePrinters and can be read to, written to and modified by
  1823. Power Users and Administrators. PSetupKillBadUserConnections is called
  1824. for each user when he/she first logs in after upgrade is complete and it
  1825. will execute in this user's context. Only executed if the old build number
  1826. is less than 2022.
  1827. Arguments:
  1828. none
  1829. Return Value:
  1830. none
  1831. --*/
  1832. {
  1833. BOOL bRC;
  1834. PCONNECTION_TO_DELETE pBadConnections = NULL;
  1835. GetBadConnsFromReg( &pBadConnections );
  1836. PruneUserOrMachineEntries( pBadConnections, TRUE );
  1837. ClearConnList( pBadConnections );
  1838. }