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.

1394 lines
35 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Nt.c
  6. Abstract:
  7. Routines to migrate Win95 printing components to NT
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 02-Jan-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. //
  14. // Data structures to gather info from the text files created on Win95 to
  15. // store the printing configuration
  16. //
  17. typedef struct _DRIVER_NODE {
  18. struct _DRIVER_NODE *pNext;
  19. DRIVER_INFO_1A DrvInfo1;
  20. PPSETUP_LOCAL_DATA pLocalData;
  21. BOOL bCantAdd;
  22. } DRIVER_NODE, *PDRIVER_NODE;
  23. typedef struct _PRINTER_NODE {
  24. struct _PRINTER_NODE *pNext;
  25. PRINTER_INFO_2A PrinterInfo2;
  26. } PRINTER_NODE, *PPRINTER_NODE;
  27. typedef struct _PORT_NODE {
  28. struct _PORT_NODE *pNext;
  29. LPSTR pPortName;
  30. } PORT_NODE, *PPORT_NODE;
  31. LPSTR pszDefaultPrinterString = NULL;
  32. PPRINTER_NODE pDefPrinter = NULL;
  33. //
  34. // They kill the migration dll if it does not finish in 3 minutes.
  35. // To prevent that I need to set this handle atleast every 3 mins
  36. //
  37. HANDLE hAlive = NULL;
  38. //
  39. // We want to lazy load ntprint.dll and mscms.dll.
  40. // Note : If we link to them our DLL will not run on Win9x
  41. //
  42. struct {
  43. HMODULE hNtPrint;
  44. pfPSetupCreatePrinterDeviceInfoList pfnCreatePrinterDeviceInfoList;
  45. pfPSetupDestroyPrinterDeviceInfoList pfnDestroyPrinterDeviceInfoList;
  46. pfPSetupBuildDriversFromPath pfnBuildDriversFromPath;
  47. pfPSetupDriverInfoFromName pfnDriverInfoFromName;
  48. pfPSetupDestroySelectedDriverInfo pfnDestroySelectedDriverInfo;
  49. pfPSetupGetLocalDataField pfnGetLocalDataField;
  50. pfPSetupFreeDrvField pfnFreeDrvField;
  51. pfPSetupProcessPrinterAdded pfnProcessPrinterAdded;
  52. pfPSetupInstallICMProfiles pfnInstallICMProfiles;
  53. pfPSetupAssociateICMProfiles pfnAssociateICMProfiles;
  54. } LAZYLOAD_INFO;
  55. VOID
  56. FreePrinterNode(
  57. IN PPRINTER_NODE pPrinterNode
  58. )
  59. /*++
  60. Routine Description:
  61. Free the memory allocated for a PRINTER_NODE element and strings in it
  62. Arguments:
  63. pPrinterNode : Points to the structure to free memory
  64. Return Value:
  65. None
  66. --*/
  67. {
  68. FreePrinterInfo2Strings(&pPrinterNode->PrinterInfo2);
  69. FreeMem(pPrinterNode);
  70. }
  71. VOID
  72. FreePrinterNodeList(
  73. IN PPRINTER_NODE pPrinterNode
  74. )
  75. /*++
  76. Routine Description:
  77. Free the memory allocated for elements in the PRINTER_NODE linked list
  78. Arguments:
  79. pPrinterNode : Points to the head of linked list to free memory
  80. Return Value:
  81. None
  82. --*/
  83. {
  84. PPRINTER_NODE pNext;
  85. while ( pPrinterNode ) {
  86. pNext = pPrinterNode->pNext;
  87. FreePrinterNode(pPrinterNode);
  88. pPrinterNode = pNext;
  89. }
  90. }
  91. VOID
  92. FreeDriverNode(
  93. IN PDRIVER_NODE pDriverNode
  94. )
  95. /*++
  96. Routine Description:
  97. Free the memory allocated for a DRIVER_NODE element and fields in it
  98. Arguments:
  99. pDriverNode : Points to the structure to free memory
  100. Return Value:
  101. None
  102. --*/
  103. {
  104. if ( pDriverNode->pLocalData )
  105. LAZYLOAD_INFO.pfnDestroySelectedDriverInfo(pDriverNode->pLocalData);
  106. FreeMem(pDriverNode->DrvInfo1.pName);
  107. FreeMem(pDriverNode);
  108. }
  109. VOID
  110. FreeDriverNodeList(
  111. IN PDRIVER_NODE pDriverNode
  112. )
  113. /*++
  114. Routine Description:
  115. Free the memory allocated for elements in the PDRIVER_NODE linked list
  116. Arguments:
  117. pDriverNode : Points to the head of linked list to free memory
  118. Return Value:
  119. None
  120. --*/
  121. {
  122. PDRIVER_NODE pNext;
  123. while ( pDriverNode ) {
  124. pNext = pDriverNode->pNext;
  125. FreeDriverNode(pDriverNode);
  126. pDriverNode = pNext;
  127. }
  128. }
  129. VOID
  130. FreePortNode(
  131. IN PPORT_NODE pPortNode
  132. )
  133. /*++
  134. Routine Description:
  135. Free the memory allocated for a PORT_NODE element and fields in it
  136. Arguments:
  137. PPORT_NODE : Points to the structure to free memory
  138. Return Value:
  139. None
  140. --*/
  141. {
  142. if (pPortNode->pPortName)
  143. {
  144. FreeMem(pPortNode->pPortName);
  145. }
  146. FreeMem(pPortNode);
  147. }
  148. VOID
  149. FreePortNodeList(
  150. IN PPORT_NODE pPortNode
  151. )
  152. /*++
  153. Routine Description:
  154. Free the memory allocated for elements in the PORT_NODE linked list
  155. Arguments:
  156. pPortNode : Points to the head of linked list to free memory
  157. Return Value:
  158. None
  159. --*/
  160. {
  161. PPORT_NODE pNext;
  162. while ( pPortNode ) {
  163. pNext = pPortNode->pNext;
  164. FreePortNode(pPortNode);
  165. pPortNode = pNext;
  166. }
  167. }
  168. PPSETUP_LOCAL_DATA
  169. FindLocalDataForDriver(
  170. IN PDRIVER_NODE pDriverList,
  171. IN LPSTR pszDriverName
  172. )
  173. /*++
  174. Routine Description:
  175. Find the local data for a given driver name from the list
  176. Arguments:
  177. Return Value:
  178. Valid PPSETUP_LOCAL_DATA on success, else NULL
  179. --*/
  180. {
  181. while ( pDriverList ) {
  182. if ( !_strcmpi(pszDriverName, pDriverList->DrvInfo1.pName) )
  183. return pDriverList->pLocalData;
  184. pDriverList = pDriverList->pNext;
  185. }
  186. return NULL;
  187. }
  188. BOOL
  189. InitLazyLoadInfo(
  190. VOID
  191. )
  192. /*++
  193. Routine Description:
  194. Initializes the LAZYLOAD_INFO structure with LoadLibrary & GetProcAddress
  195. Arguments:
  196. None
  197. Return Value:
  198. TRUE on success, FALSE else
  199. --*/
  200. {
  201. if ( LAZYLOAD_INFO.hNtPrint = LoadLibraryUsingFullPathA("ntprint.dll") ) {
  202. (FARPROC)LAZYLOAD_INFO.pfnCreatePrinterDeviceInfoList
  203. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  204. "PSetupCreatePrinterDeviceInfoList");
  205. (FARPROC)LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList
  206. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  207. "PSetupDestroyPrinterDeviceInfoList");
  208. (FARPROC)LAZYLOAD_INFO.pfnBuildDriversFromPath
  209. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  210. "PSetupBuildDriversFromPath");
  211. (FARPROC)LAZYLOAD_INFO.pfnDriverInfoFromName
  212. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  213. "PSetupDriverInfoFromName");
  214. (FARPROC)LAZYLOAD_INFO.pfnDestroySelectedDriverInfo
  215. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  216. "PSetupDestroySelectedDriverInfo");
  217. (FARPROC)LAZYLOAD_INFO.pfnGetLocalDataField
  218. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  219. "PSetupGetLocalDataField");
  220. (FARPROC)LAZYLOAD_INFO.pfnFreeDrvField
  221. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  222. "PSetupFreeDrvField");
  223. (FARPROC)LAZYLOAD_INFO.pfnProcessPrinterAdded
  224. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  225. "PSetupProcessPrinterAdded");
  226. (FARPROC)LAZYLOAD_INFO.pfnInstallICMProfiles
  227. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  228. "PSetupInstallICMProfiles");
  229. (FARPROC)LAZYLOAD_INFO.pfnAssociateICMProfiles
  230. = GetProcAddress(LAZYLOAD_INFO.hNtPrint,
  231. "PSetupAssociateICMProfiles");
  232. if ( LAZYLOAD_INFO.pfnCreatePrinterDeviceInfoList &&
  233. LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList &&
  234. LAZYLOAD_INFO.pfnBuildDriversFromPath &&
  235. LAZYLOAD_INFO.pfnDriverInfoFromName &&
  236. LAZYLOAD_INFO.pfnDestroySelectedDriverInfo &&
  237. LAZYLOAD_INFO.pfnGetLocalDataField &&
  238. LAZYLOAD_INFO.pfnFreeDrvField &&
  239. LAZYLOAD_INFO.pfnProcessPrinterAdded &&
  240. LAZYLOAD_INFO.pfnInstallICMProfiles &&
  241. LAZYLOAD_INFO.pfnAssociateICMProfiles ) {
  242. #ifdef VERBOSE
  243. DebugMsg("Succesfully loaded Ntprint.dll");
  244. #endif
  245. return TRUE;
  246. }
  247. }
  248. if ( LAZYLOAD_INFO.hNtPrint )
  249. {
  250. FreeLibrary(LAZYLOAD_INFO.hNtPrint);
  251. LAZYLOAD_INFO.hNtPrint = NULL;
  252. }
  253. return FALSE;
  254. }
  255. VOID
  256. DeleteWin95Files(
  257. )
  258. /*++
  259. Routine Description:
  260. Read the migrate.inf and delete the files which are not needed on NT.
  261. Arguments:
  262. None
  263. Return Value:
  264. None
  265. --*/
  266. {
  267. HINF hInf;
  268. CHAR szPath[MAX_PATH];
  269. LONG Count, Index;
  270. INFCONTEXT InfContext;
  271. StringCchPrintfA(szPath, SIZECHARS(szPath), "%s\\%s", UpgradeData.pszDir, "migrate.inf");
  272. hInf = SetupOpenInfFileA(szPath, NULL, INF_STYLE_WIN4, NULL);
  273. if ( hInf == INVALID_HANDLE_VALUE )
  274. return;
  275. //
  276. // We will only do the deleting part here. Files which are handled by
  277. // the core migration dll do not have a destination directory since we
  278. // are recreating the printing environment from scratch
  279. //
  280. if ( (Count = SetupGetLineCountA(hInf, "Moved")) != -1 ) {
  281. for ( Index = 0 ; Index < Count ; ++Index ) {
  282. if ( SetupGetLineByIndexA(hInf, "Moved", Index, &InfContext) &&
  283. SetupGetStringFieldA(&InfContext, 0, szPath,
  284. SIZECHARS(szPath), NULL) )
  285. DeleteFileA(szPath);
  286. }
  287. }
  288. SetupCloseInfFile(hInf);
  289. }
  290. BOOL
  291. ReadWin9xPrintConfig(
  292. IN OUT PDRIVER_NODE *ppDriverNode,
  293. IN OUT PPRINTER_NODE *ppPrinterNode,
  294. IN OUT PPORT_NODE *ppPortNode
  295. )
  296. /*++
  297. Routine Description:
  298. Reads the Win9x printing configuration we stored in the text file
  299. so that printing components can be upgraded
  300. Arguments:
  301. ppDriverNode : Gives the list of drivers on Win9x
  302. ppPrinterNode : Gives the list of printers on Win9x
  303. Return Value:
  304. TRUE on successfully reading the config information, FALSE else
  305. --*/
  306. {
  307. BOOL bFail = FALSE, bRet = FALSE;
  308. HANDLE hFile = INVALID_HANDLE_VALUE;
  309. CHAR c, szLine[2*MAX_PATH];
  310. DWORD dwCount, dwIndex, dwSize;
  311. PDRIVER_NODE pDrv = NULL;
  312. PPRINTER_NODE pPrn;
  313. PPORT_NODE pPort;
  314. if(!SUCCEEDED(StringCchPrintfA(szLine, SIZECHARS(szLine), "%s\\%s", UpgradeData.pszDir, "print95.txt")))
  315. {
  316. goto Cleanup;
  317. }
  318. hFile = CreateFileA(szLine,
  319. GENERIC_READ,
  320. FILE_SHARE_READ,
  321. NULL,
  322. OPEN_EXISTING,
  323. FILE_ATTRIBUTE_NORMAL |
  324. FILE_FLAG_SEQUENTIAL_SCAN,
  325. NULL);
  326. if ( hFile == INVALID_HANDLE_VALUE )
  327. goto Cleanup;
  328. dwSize = sizeof(szLine)/sizeof(szLine[0]);
  329. //
  330. // First we have the drivers
  331. //
  332. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  333. strncmp(szLine, "[PrinterDrivers]", strlen("[PrinterDrivers]")) )
  334. goto Cleanup;
  335. do {
  336. //
  337. // Skip blanks
  338. //
  339. do {
  340. c = (CHAR) My_fgetc(hFile);
  341. } while ( c == ' ');
  342. //
  343. // If we hit EOF it is an error. Configuration was not written properly
  344. // If we hit a new-line then we are at the end of the section
  345. //
  346. if ( c == EOF )
  347. goto Cleanup;
  348. else if ( c == '\n' )
  349. break; // This is the normal exit from the do loop
  350. if ( isdigit(c) ) {
  351. //
  352. // Put the string lengh digit back
  353. //
  354. if ( !My_ungetc(hFile) )
  355. goto Cleanup;
  356. }
  357. if ( !(pDrv = AllocMem(sizeof(DRIVER_NODE))) )
  358. goto Cleanup;
  359. ReadString(hFile, "", &pDrv->DrvInfo1.pName, FALSE, &bFail);
  360. if ( bFail ) {
  361. FreeDriverNode(pDrv);
  362. goto Cleanup;
  363. }
  364. pDrv->pNext = *ppDriverNode;
  365. *ppDriverNode = pDrv;
  366. } while ( !bFail );
  367. //
  368. // Now we have port info
  369. //
  370. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  371. strncmp(szLine, "[Ports]", strlen("[Ports]")) )
  372. goto Cleanup;
  373. do {
  374. //
  375. // Skip blanks
  376. //
  377. do {
  378. c = (CHAR) My_fgetc(hFile);
  379. } while ( isspace(c) && c != '\n' );
  380. //
  381. // EOF can happen if no ports and no printers, else it's an error
  382. //
  383. if ( c == EOF)
  384. {
  385. if (!pDrv)
  386. {
  387. bRet = TRUE;
  388. }
  389. goto Cleanup;
  390. }
  391. //
  392. // a blank line means the end of the port info section
  393. //
  394. if (c == '\n')
  395. break;
  396. if ( c != 'P' || !My_ungetc(hFile) )
  397. goto Cleanup;
  398. //
  399. // Create port node
  400. //
  401. if ( !(pPort = AllocMem(sizeof(PORT_NODE))) )
  402. {
  403. goto Cleanup;
  404. }
  405. ReadString(hFile, "PortName:", &pPort->pPortName, FALSE, &bFail);
  406. if (bFail)
  407. {
  408. FreePortNode(pPort);
  409. goto Cleanup;
  410. }
  411. pPort->pNext = *ppPortNode;
  412. *ppPortNode = pPort;
  413. } while ( !bFail );
  414. //
  415. // Now we have printer info
  416. //
  417. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  418. strncmp(szLine, "[Printers]", strlen("[Printers]")) )
  419. goto Cleanup;
  420. do {
  421. c = (CHAR) My_fgetc(hFile);
  422. if ( c == EOF || c == '\n' )
  423. break; // Normal exit
  424. if ( c != 'S' || !My_ungetc(hFile) )
  425. goto Cleanup;
  426. if ( !(pPrn = AllocMem(sizeof(PRINTER_NODE))) )
  427. goto Cleanup;
  428. ReadPrinterInfo2(hFile, &pPrn->PrinterInfo2, &bFail);
  429. if ( bFail ) {
  430. FreePrinterNode(pPrn);
  431. goto Cleanup;
  432. }
  433. pPrn->pNext = *ppPrinterNode;
  434. *ppPrinterNode = pPrn;
  435. } while ( !bFail );
  436. bRet = TRUE;
  437. Cleanup:
  438. if ( hFile != INVALID_HANDLE_VALUE )
  439. CloseHandle(hFile);
  440. return bRet && !bFail;
  441. }
  442. BOOL
  443. CheckAndAddMonitor(
  444. IN LPDRIVER_INFO_6W pDrvInfo6
  445. )
  446. /*++
  447. Routine Description:
  448. Check if there is a language monitor associated with the given driver
  449. and add it.
  450. Arguments:
  451. Return Value:
  452. TRUE on success, FALSE on failure
  453. None
  454. --*/
  455. {
  456. MONITOR_INFO_2W MonitorInfo2;
  457. LPWSTR psz = pDrvInfo6->pMonitorName;
  458. LPSTR pszStr;
  459. if ( psz && *psz ) {
  460. MonitorInfo2.pName = psz;
  461. MonitorInfo2.pEnvironment = NULL;
  462. MonitorInfo2.pDLLName = (LPWSTR) (psz+wcslen(psz)+1);
  463. //
  464. // Add is succesful, or monitor is already installed?
  465. //
  466. if ( AddMonitorW(NULL, 2, (LPBYTE) &MonitorInfo2) ||
  467. GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED ) {
  468. return TRUE;
  469. } else {
  470. if ( pszStr = ErrorMsg() ) {
  471. LogError(LogSevError, IDS_ADDMONITOR_FAILED,
  472. psz, pszStr);
  473. FreeMem(pszStr);
  474. }
  475. return FALSE;
  476. }
  477. }
  478. return TRUE;
  479. }
  480. VOID
  481. KeepAliveThread(
  482. HANDLE hRunning
  483. )
  484. /*++
  485. Routine Description:
  486. Printing migration may take a long time depending on number of printers and
  487. how long spooler takes to return. To inform setup that we are still alive
  488. I need to set a named event atleast once every 3 minutes
  489. Arguments:
  490. hRunning : When this gets closed we know processing is done
  491. Return Value:
  492. None
  493. --*/
  494. {
  495. //
  496. // Every 30 seconds set the global event telling we are still alive
  497. //
  498. do {
  499. SetEvent(hAlive);
  500. } while ( WAIT_TIMEOUT == WaitForSingleObject(hRunning, 1000*30) );
  501. CloseHandle(hAlive);
  502. hAlive = NULL;
  503. }
  504. VOID
  505. UpgradePrinterDrivers(
  506. IN PDRIVER_NODE pDriverNode,
  507. IN HDEVINFO hDevInfo,
  508. IN OUT LPBOOL pbFail
  509. )
  510. /*++
  511. Routine Description:
  512. Upgrades printer drivers by doing the file copy operations and calling
  513. AddPrinterDriver on spooler
  514. Arguments:
  515. pUpgradableDrvNode : List of drivers to upgrade
  516. pbFail : Set on an error -- no more processing needed
  517. Return Value:
  518. None
  519. --*/
  520. {
  521. BOOL bDriverToUpgrade = FALSE;
  522. LPWSTR pszDriverW, pszICMW;
  523. LPSTR pszDriverA, pszStr;
  524. PDRIVER_NODE pCur;
  525. DRIVER_FIELD DrvField;
  526. //
  527. // Set device install parameters so ntprint.dll will just queue up the
  528. // driver files and return without doing the copy. We will commit the
  529. // file queue at the end
  530. //
  531. if ( !InitFileCopyOnNT(hDevInfo) ) {
  532. *pbFail = TRUE;
  533. goto Cleanup;
  534. }
  535. //
  536. // Now for each printer driver call ntprint.dll to queue up the driver files
  537. // If it fails log an error
  538. //
  539. for ( pCur = pDriverNode ; pCur ; pCur = pCur->pNext ) {
  540. pszDriverA = pCur->DrvInfo1.pName;
  541. if ( (pszDriverW = AllocStrWFromStrA(pszDriverA)) &&
  542. (pCur->pLocalData = LAZYLOAD_INFO.pfnDriverInfoFromName(
  543. hDevInfo, (LPSTR)pszDriverW)) &&
  544. SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  545. hDevInfo,
  546. NULL) ) {
  547. bDriverToUpgrade = TRUE;
  548. } else {
  549. pCur->bCantAdd = TRUE;
  550. }
  551. FreeMem(pszDriverW);
  552. pszDriverW = NULL;
  553. }
  554. if ( !bDriverToUpgrade )
  555. goto Cleanup;
  556. #ifdef VERBOSE
  557. DebugMsg("Starting file copy ...");
  558. #endif
  559. //
  560. // Now commit the file queue to copy the files
  561. //
  562. if ( !CommitFileQueueToCopyFiles(hDevInfo) ) {
  563. *pbFail = TRUE;
  564. if ( pszStr = ErrorMsg() ) {
  565. LogError(LogSevError, IDS_DRIVERS_UPGRADE_FAILED, pszStr);
  566. FreeMem(pszStr);
  567. pszStr = NULL;
  568. }
  569. goto Cleanup;
  570. }
  571. #ifdef VERBOSE
  572. DebugMsg("... files copied successfully");
  573. #endif
  574. //
  575. // Now call spooler to install the printer driver. Also install the
  576. // ICM profiles associated with the printer driver
  577. //
  578. for ( pCur = pDriverNode ; pCur ; pCur = pCur->pNext ) {
  579. //
  580. // We already logged an error if bCantAdd is TRUE
  581. //
  582. if ( pCur->bCantAdd )
  583. continue;
  584. DrvField.Index = DRV_INFO_6;
  585. DrvField.pDriverInfo6 = NULL;
  586. if ( !LAZYLOAD_INFO.pfnGetLocalDataField(pCur->pLocalData,
  587. PlatformX86,
  588. &DrvField) ||
  589. !CheckAndAddMonitor((LPDRIVER_INFO_6W) DrvField.pDriverInfo6) ||
  590. !AddPrinterDriverW(NULL,
  591. 6,
  592. (LPBYTE)DrvField.pDriverInfo6) ) {
  593. if ( pszStr = ErrorMsg() ) {
  594. LogError(LogSevError, IDS_ADDDRIVER_FAILED, pCur->DrvInfo1.pName, pszStr);
  595. FreeMem(pszStr);
  596. pszStr = NULL;
  597. }
  598. }
  599. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  600. DrvField.Index = ICM_FILES;
  601. DrvField.pszzICMFiles = NULL;
  602. if ( !LAZYLOAD_INFO.pfnGetLocalDataField(pCur->pLocalData,
  603. PlatformX86,
  604. &DrvField) ) {
  605. continue;
  606. }
  607. if ( DrvField.pszzICMFiles )
  608. LAZYLOAD_INFO.pfnInstallICMProfiles(NULL,
  609. DrvField.pszzICMFiles);
  610. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  611. }
  612. Cleanup:
  613. return;
  614. }
  615. typedef BOOL (WINAPI *P_XCV_DATA_W)(
  616. IN HANDLE hXcv,
  617. IN PCWSTR pszDataName,
  618. IN PBYTE pInputData,
  619. IN DWORD cbInputData,
  620. OUT PBYTE pOutputData,
  621. IN DWORD cbOutputData,
  622. OUT PDWORD pcbOutputNeeded,
  623. OUT PDWORD pdwStatus
  624. );
  625. BOOL
  626. AddLocalPort(
  627. IN LPSTR pPortName
  628. )
  629. /*++
  630. Routine Description:
  631. Adds a local port
  632. Arguments:
  633. pPortName : Name of the local port to add
  634. Return Value:
  635. FALSE if a port can't be added.
  636. --*/
  637. {
  638. PRINTER_DEFAULTS PrinterDefault = {NULL, NULL, SERVER_ACCESS_ADMINISTER};
  639. HANDLE hXcvMon = NULL;
  640. BOOL bReturn = FALSE;
  641. if (OpenPrinterA(",XcvMonitor Local Port", &hXcvMon, &PrinterDefault))
  642. {
  643. DWORD cbOutputNeeded = 0;
  644. DWORD Status = NO_ERROR;
  645. WCHAR *pUnicodePortName = NULL;
  646. P_XCV_DATA_W pXcvData = NULL;
  647. HMODULE hWinSpool = NULL;
  648. //
  649. // if I implib-link to XcvData, loading the migrate.dll on Win9x will fail !
  650. //
  651. hWinSpool = LoadLibraryUsingFullPathA("winspool.drv");
  652. if (!hWinSpool)
  653. {
  654. DebugMsg("LoadLibrary on winspool.drv failed");
  655. goto Done;
  656. }
  657. pXcvData = (P_XCV_DATA_W) GetProcAddress(hWinSpool, "XcvDataW");
  658. if (!pXcvData)
  659. {
  660. DebugMsg("GetProcAddress on winspool.drv failed");
  661. goto Done;
  662. }
  663. pUnicodePortName = AllocStrWFromStrA(pPortName);
  664. if (pUnicodePortName)
  665. {
  666. bReturn = (*pXcvData)(hXcvMon,
  667. L"AddPort",
  668. (LPBYTE) pUnicodePortName,
  669. (wcslen(pUnicodePortName) +1) * sizeof(WCHAR),
  670. NULL,
  671. 0,
  672. &cbOutputNeeded,
  673. &Status
  674. );
  675. FreeMem(pUnicodePortName);
  676. pUnicodePortName = NULL;
  677. }
  678. Done:
  679. if (hWinSpool)
  680. {
  681. FreeLibrary(hWinSpool);
  682. }
  683. ClosePrinter(hXcvMon);
  684. }
  685. return bReturn;
  686. }
  687. VOID
  688. UpgradePrinters(
  689. IN PPRINTER_NODE pPrinterNode,
  690. IN PDRIVER_NODE pDriverNode,
  691. IN PPORT_NODE *ppPortNode,
  692. IN HDEVINFO hDevInfo
  693. )
  694. /*++
  695. Routine Description:
  696. Upgrade printers on NT
  697. Arguments:
  698. pPrinterNode : Gives the list giving information about the printers
  699. which existed on Win9x
  700. Return Value:
  701. None
  702. --*/
  703. {
  704. DWORD dwLen, dwLastError;
  705. LPSTR pszStr, pszPrinterNameA;
  706. LPWSTR pszPrinterNameW;
  707. HANDLE hPrinter;
  708. DRIVER_FIELD DrvField;
  709. PPSETUP_LOCAL_DATA pLocalData;
  710. PPORT_NODE pCurPort, pPrevPort = NULL;
  711. DWORD dwSize;
  712. LPSTR pszVendorSetupA = NULL;
  713. for ( ; pPrinterNode ; pPrinterNode = pPrinterNode->pNext ) {
  714. pszPrinterNameA = pPrinterNode->PrinterInfo2.pPrinterName;
  715. //
  716. // check whether this printer uses a non-standard local file port
  717. //
  718. for (pCurPort = *ppPortNode; pCurPort != NULL; pPrevPort = pCurPort, pCurPort = pCurPort->pNext)
  719. {
  720. if (lstrcmpi(pPrinterNode->PrinterInfo2.pPortName, pCurPort->pPortName) == 0)
  721. {
  722. //
  723. // Create the port
  724. //
  725. AddLocalPort(pCurPort->pPortName);
  726. //
  727. // remove it from the list
  728. //
  729. if (pCurPort == *ppPortNode)
  730. {
  731. *ppPortNode = pCurPort->pNext;
  732. }
  733. else
  734. {
  735. pPrevPort->pNext = pCurPort->pNext;
  736. }
  737. FreePortNode(pCurPort);
  738. break;
  739. }
  740. }
  741. hPrinter = AddPrinterA(NULL,
  742. 2,
  743. (LPBYTE)&pPrinterNode->PrinterInfo2);
  744. if ( !hPrinter ) {
  745. dwLastError = GetLastError();
  746. //
  747. // If driver is unknown we already logged warned the user
  748. // If printer already exists it is ok (for Fax printer this is true)
  749. //
  750. if ( dwLastError != ERROR_UNKNOWN_PRINTER_DRIVER &&
  751. dwLastError != ERROR_INVALID_PRINTER_NAME &&
  752. dwLastError != ERROR_PRINTER_ALREADY_EXISTS &&
  753. (pszStr = ErrorMsg()) ) {
  754. LogError(LogSevError,
  755. IDS_ADDPRINTER_FAILED,
  756. pszPrinterNameA,
  757. pszStr);
  758. FreeMem(pszStr);
  759. pszStr = NULL;
  760. }
  761. continue;
  762. }
  763. pLocalData = FindLocalDataForDriver(pDriverNode,
  764. pPrinterNode->PrinterInfo2.pDriverName);
  765. pszPrinterNameW = AllocStrWFromStrA(pszPrinterNameA);
  766. if ( pLocalData && pszPrinterNameW ) {
  767. DrvField.Index = ICM_FILES;
  768. DrvField.pszzICMFiles = NULL;
  769. if ( LAZYLOAD_INFO.pfnGetLocalDataField(pLocalData,
  770. PlatformX86,
  771. &DrvField) ) {
  772. if ( DrvField.pszzICMFiles )
  773. LAZYLOAD_INFO.pfnAssociateICMProfiles(
  774. (LPTSTR)pszPrinterNameW,
  775. DrvField.pszzICMFiles);
  776. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  777. }
  778. LAZYLOAD_INFO.pfnProcessPrinterAdded(hDevInfo,
  779. pLocalData,
  780. (LPTSTR)pszPrinterNameW,
  781. INVALID_HANDLE_VALUE);
  782. dwSize = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)(pLocalData->InfInfo.pszVendorSetup),
  783. -1, NULL, 0, NULL, NULL);
  784. if (dwSize > 0)
  785. {
  786. pszVendorSetupA = (LPSTR)AllocMem( dwSize );
  787. if (pszVendorSetupA)
  788. {
  789. if (WideCharToMultiByte (CP_ACP, 0, (LPCWSTR)(pLocalData->InfInfo.pszVendorSetup),
  790. -1, pszVendorSetupA, dwSize, NULL, NULL))
  791. {
  792. WriteVendorSetupInfoInRegistry( pszVendorSetupA, pszPrinterNameA );
  793. }
  794. FreeMem( pszVendorSetupA );
  795. pszVendorSetupA = NULL;
  796. }
  797. }
  798. }
  799. //
  800. // Default printer will be the one with PRINTER_ATTRIBUTE_DEFAULT attribute
  801. // If the Win95 default printer could not be added to NT we will set the
  802. // first printer as the default printer
  803. //
  804. if ( (pPrinterNode->PrinterInfo2.Attributes
  805. & PRINTER_ATTRIBUTE_DEFAULT) ||
  806. !pDefPrinter )
  807. pDefPrinter = pPrinterNode;
  808. FreeMem(pszPrinterNameW);
  809. ClosePrinter(hPrinter);
  810. }
  811. if ( pDefPrinter )
  812. pszDefaultPrinterString = GetDefPrnString(
  813. pDefPrinter->PrinterInfo2.pPrinterName);
  814. }
  815. HDEVINFO
  816. PrinterDevInfo(
  817. IN OUT LPBOOL pbFail
  818. )
  819. /*++
  820. --*/
  821. {
  822. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  823. if ( *pbFail || !InitLazyLoadInfo() ) {
  824. *pbFail = TRUE;
  825. goto Cleanup;
  826. }
  827. hDevInfo = LAZYLOAD_INFO.pfnCreatePrinterDeviceInfoList(INVALID_HANDLE_VALUE);
  828. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  829. !LAZYLOAD_INFO.pfnBuildDriversFromPath(hDevInfo,
  830. (LPSTR)L"ntprint.inf",
  831. TRUE) ) {
  832. *pbFail = TRUE;
  833. goto Cleanup;
  834. }
  835. #ifdef VERBOSE
  836. DebugMsg("Built the list of printer drivers from ntprint.inf");
  837. #endif
  838. if ( *pbFail && hDevInfo != INVALID_HANDLE_VALUE ) {
  839. LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList(hDevInfo);
  840. hDevInfo = INVALID_HANDLE_VALUE;
  841. }
  842. Cleanup:
  843. return hDevInfo;
  844. }
  845. LONG
  846. CALLBACK
  847. InitializeNT(
  848. IN LPCWSTR pszWorkingDir,
  849. IN LPCWSTR pszSourceDir,
  850. LPVOID Reserved
  851. )
  852. /*++
  853. Routine Description:
  854. Setup calls this to intialize us on NT side
  855. Arguments:
  856. pszWorkingDir : Gives the working directory assigned for printing
  857. pszSourceDir : Source location for NT distribution files
  858. Reserved : Leave it alone
  859. Return Value:
  860. Win32 error code
  861. --*/
  862. {
  863. BOOL bFail = FALSE;
  864. DWORD dwReturn, ThreadId;
  865. HANDLE hRunning = NULL, hThread;
  866. HDSKSPC DiskSpace;
  867. LPSTR pszStr;
  868. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  869. PDRIVER_NODE pDriverNode = NULL;
  870. PPRINTER_NODE pPrinterNode = NULL;
  871. PPORT_NODE pPortNode = NULL;
  872. #ifdef VERBOSE
  873. DebugMsg("InitializeNT : %ws, %ws", pszSourceDir, pszWorkingDir);
  874. #endif
  875. UpgradeData.pszDir = AllocStrAFromStrW(pszWorkingDir);
  876. UpgradeData.pszSourceW = AllocStrW(pszSourceDir);
  877. UpgradeData.pszSourceA = AllocStrAFromStrW(pszSourceDir);
  878. if ( !UpgradeData.pszDir ||
  879. !UpgradeData.pszSourceW ||
  880. !UpgradeData.pszSourceA ) {
  881. return GetLastError();
  882. }
  883. if ( (hAlive = OpenEventA(EVENT_MODIFY_STATE, FALSE, "MigDllAlive")) &&
  884. (hRunning = CreateEventA(NULL, FALSE, FALSE, NULL)) &&
  885. (hThread = CreateThread(NULL, 0,
  886. (LPTHREAD_START_ROUTINE)KeepAliveThread,
  887. hRunning,
  888. 0, &ThreadId)) )
  889. CloseHandle(hThread);
  890. SetupOpenLog(FALSE);
  891. DeleteWin95Files();
  892. if ( !ReadWin9xPrintConfig(&pDriverNode, &pPrinterNode, &pPortNode) ) {
  893. bFail = TRUE;
  894. DebugMsg("Unable to read Windows 9x printing configuration");
  895. goto Cleanup;
  896. }
  897. #ifdef VERBOSE
  898. DebugMsg("Succesfully read Windows 9x printing configuration");
  899. #endif
  900. //
  901. // If no printers or drivers found nothing to do
  902. //
  903. if ( !pDriverNode && !pPrinterNode )
  904. goto Cleanup;
  905. if ( (hDevInfo = PrinterDevInfo(&bFail)) == INVALID_HANDLE_VALUE )
  906. goto Cleanup;
  907. UpgradePrinterDrivers(pDriverNode, hDevInfo, &bFail);
  908. UpgradePrinters(pPrinterNode, pDriverNode, &pPortNode, hDevInfo);
  909. MakeACopyOfMigrateDll( UpgradeData.pszDir );
  910. Cleanup:
  911. SetupCloseLog();
  912. if ( bFail && (pszStr = ErrorMsg()) ) {
  913. DebugMsg("Printing migration failed. %s", pszStr);
  914. FreeMem(pszStr);
  915. pszStr = NULL;
  916. }
  917. FreePrinterNodeList(pPrinterNode);
  918. FreeDriverNodeList(pDriverNode);
  919. FreePortNodeList(pPortNode);
  920. pPrinterNode = NULL;
  921. pDriverNode = NULL;
  922. pPortNode = NULL;
  923. if ( hDevInfo != INVALID_HANDLE_VALUE )
  924. LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList(hDevInfo);
  925. if ( LAZYLOAD_INFO.hNtPrint )
  926. FreeLibrary(LAZYLOAD_INFO.hNtPrint);
  927. if ( bFail ) {
  928. if ( (dwReturn = GetLastError()) == ERROR_SUCCESS ) {
  929. ASSERT(dwReturn != ERROR_SUCCESS);
  930. dwReturn = STG_E_UNKNOWN;
  931. }
  932. } else {
  933. SetupNetworkPrinterUpgrade(UpgradeData.pszDir);
  934. dwReturn = ERROR_SUCCESS;
  935. #ifdef VERBOSE
  936. DebugMsg("InitializeNT returning success");
  937. #endif
  938. }
  939. if ( hRunning )
  940. CloseHandle(hRunning);
  941. while (hAlive)
  942. Sleep(100); // Check after 0.1 second for the main thread to die
  943. return dwReturn;
  944. }
  945. DWORD
  946. MySetDefaultPrinter(
  947. IN HKEY hUserRegKey,
  948. IN LPSTR pszDefaultPrinterString
  949. )
  950. /*++
  951. Routine Description:
  952. Sets the default printer for the user by writing it to the registry
  953. Arguments:
  954. Return Value:
  955. --*/
  956. {
  957. DWORD dwReturn;
  958. HKEY hKey = NULL;
  959. //
  960. // Create the printers key in the user hive and write DeviceOld value
  961. //
  962. dwReturn = RegCreateKeyExA(hUserRegKey,
  963. "Printers",
  964. 0,
  965. NULL,
  966. 0,
  967. KEY_ALL_ACCESS,
  968. NULL,
  969. &hKey,
  970. NULL);
  971. if ( dwReturn == ERROR_SUCCESS ) {
  972. dwReturn = RegSetValueExA(hKey,
  973. "DeviceOld",
  974. 0,
  975. REG_SZ,
  976. (LPBYTE)pszDefaultPrinterString,
  977. (strlen(pszDefaultPrinterString) + 1)
  978. * sizeof(CHAR));
  979. RegCloseKey(hKey);
  980. }
  981. return dwReturn;
  982. }
  983. LONG
  984. CALLBACK
  985. MigrateUserNT(
  986. IN HINF hUnattendInf,
  987. IN HKEY hUserRegKey,
  988. IN LPCWSTR pszUserName,
  989. LPVOID Reserved
  990. )
  991. /*++
  992. Routine Description:
  993. Migrate user settings
  994. Arguments:
  995. Return Value:
  996. --*/
  997. {
  998. LPSTR pszStr;
  999. DWORD dwReturn = ERROR_SUCCESS;
  1000. #ifdef VERBOSE
  1001. DebugMsg("Migrating settings for %ws", pszUserName);
  1002. #endif
  1003. if ( pszDefaultPrinterString ) {
  1004. dwReturn = MySetDefaultPrinter(hUserRegKey,
  1005. pszDefaultPrinterString);
  1006. if ( dwReturn )
  1007. DebugMsg("MySetDefaultPrinter failed with %d", dwReturn);
  1008. }
  1009. if ( bDoNetPrnUpgrade ) {
  1010. if ( ProcessNetPrnUpgradeForUser(hUserRegKey) )
  1011. ++dwRunOnceCount;
  1012. else {
  1013. if ( dwReturn == ERROR_SUCCESS )
  1014. dwReturn = GetLastError();
  1015. DebugMsg("ProcessNetPrnUpgradeForUser failed with %d", dwReturn);
  1016. }
  1017. }
  1018. #ifdef VERBOSE
  1019. if ( dwReturn )
  1020. DebugMsg("MigrateUserNT failed with %d", dwReturn);
  1021. else
  1022. DebugMsg("MigrateUserNT succesful");
  1023. #endif
  1024. return dwReturn;
  1025. }
  1026. LONG
  1027. CALLBACK
  1028. MigrateSystemNT(
  1029. IN HINF hUnattendInf,
  1030. LPVOID Reserved
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. Process system setttings for printing. All the printing setting are
  1035. migrated in InitializeNT since we need to know the default printer for
  1036. each user in the MigrateSystemNT call
  1037. Arguments:
  1038. hUnattendInf : Handle to the unattended INF
  1039. Return Value:
  1040. Win32 error code
  1041. --*/
  1042. {
  1043. WriteRunOnceCount();
  1044. return ERROR_SUCCESS;
  1045. }
  1046. //
  1047. // The following are to make sure if setup changes the header file they
  1048. // first tell me (otherwise they will break build of this)
  1049. //
  1050. P_INITIALIZE_NT pfnInitializeNT = InitializeNT;
  1051. P_MIGRATE_USER_NT pfnMigrateUserNt = MigrateUserNT;
  1052. P_MIGRATE_SYSTEM_NT pfnMigrateSystemNT = MigrateSystemNT;