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.

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