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.

1430 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. sprintf(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;
  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. sprintf(szLine, "%s\\%s", UpgradeData.pszDir, "print95.txt");
  315. hFile = CreateFileA(szLine,
  316. GENERIC_READ,
  317. FILE_SHARE_READ,
  318. NULL,
  319. OPEN_EXISTING,
  320. FILE_ATTRIBUTE_NORMAL |
  321. FILE_FLAG_SEQUENTIAL_SCAN,
  322. NULL);
  323. if ( hFile == INVALID_HANDLE_VALUE )
  324. goto Cleanup;
  325. dwSize = sizeof(szLine)/sizeof(szLine[0]);
  326. //
  327. // First we have the drivers
  328. //
  329. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  330. strncmp(szLine, "[PrinterDrivers]", strlen("[PrinterDrivers]")) )
  331. goto Cleanup;
  332. do {
  333. //
  334. // Skip blanks
  335. //
  336. do {
  337. c = (CHAR) My_fgetc(hFile);
  338. } while ( c == ' ');
  339. //
  340. // If we hit EOF it is an error. Configuration was not written properly
  341. // If we hit a new-line then we are at the end of the section
  342. //
  343. if ( c == EOF )
  344. goto Cleanup;
  345. else if ( c == '\n' )
  346. break; // This is the normal exit from the do loop
  347. if ( isdigit(c) ) {
  348. //
  349. // Put the string lengh digit back
  350. //
  351. if ( !My_ungetc(hFile) )
  352. goto Cleanup;
  353. }
  354. if ( !(pDrv = AllocMem(sizeof(DRIVER_NODE))) )
  355. goto Cleanup;
  356. ReadString(hFile, "", &pDrv->DrvInfo1.pName, FALSE, &bFail);
  357. if ( bFail ) {
  358. FreeDriverNode(pDrv);
  359. goto Cleanup;
  360. }
  361. pDrv->pNext = *ppDriverNode;
  362. *ppDriverNode = pDrv;
  363. } while ( !bFail );
  364. //
  365. // Now we have port info
  366. //
  367. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  368. strncmp(szLine, "[Ports]", strlen("[Ports]")) )
  369. goto Cleanup;
  370. do {
  371. //
  372. // Skip blanks
  373. //
  374. do {
  375. c = (CHAR) My_fgetc(hFile);
  376. } while ( isspace(c) && c != '\n' );
  377. //
  378. // EOF can happen if no ports and no printers, else it's an error
  379. //
  380. if ( c == EOF)
  381. {
  382. if (!pDrv)
  383. {
  384. bRet = TRUE;
  385. }
  386. goto Cleanup;
  387. }
  388. //
  389. // a blank line means the end of the port info section
  390. //
  391. if (c == '\n')
  392. break;
  393. if ( c != 'P' || !My_ungetc(hFile) )
  394. goto Cleanup;
  395. //
  396. // Create port node
  397. //
  398. if ( !(pPort = AllocMem(sizeof(PORT_NODE))) )
  399. {
  400. goto Cleanup;
  401. }
  402. ReadString(hFile, "PortName:", &pPort->pPortName, FALSE, &bFail);
  403. if (bFail)
  404. {
  405. FreePortNode(pPort);
  406. goto Cleanup;
  407. }
  408. pPort->pNext = *ppPortNode;
  409. *ppPortNode = pPort;
  410. } while ( !bFail );
  411. //
  412. // Now we have printer info
  413. //
  414. if ( My_fgets(szLine, dwSize, hFile) == NULL ||
  415. strncmp(szLine, "[Printers]", strlen("[Printers]")) )
  416. goto Cleanup;
  417. do {
  418. c = (CHAR) My_fgetc(hFile);
  419. if ( c == EOF || c == '\n' )
  420. break; // Normal exit
  421. if ( c != 'S' || !My_ungetc(hFile) )
  422. goto Cleanup;
  423. if ( !(pPrn = AllocMem(sizeof(PRINTER_NODE))) )
  424. goto Cleanup;
  425. ReadPrinterInfo2(hFile, &pPrn->PrinterInfo2, &bFail);
  426. if ( bFail ) {
  427. FreePrinterNode(pPrn);
  428. goto Cleanup;
  429. }
  430. pPrn->pNext = *ppPrinterNode;
  431. *ppPrinterNode = pPrn;
  432. } while ( !bFail );
  433. bRet = TRUE;
  434. Cleanup:
  435. if ( hFile != INVALID_HANDLE_VALUE )
  436. CloseHandle(hFile);
  437. return bRet && !bFail;
  438. }
  439. BOOL
  440. CheckAndAddMonitor(
  441. IN LPDRIVER_INFO_6W pDrvInfo6
  442. )
  443. /*++
  444. Routine Description:
  445. Check if there is a language monitor associated with the given driver
  446. and add it.
  447. Arguments:
  448. Return Value:
  449. TRUE on success, FALSE on failure
  450. None
  451. --*/
  452. {
  453. MONITOR_INFO_2W MonitorInfo2;
  454. LPWSTR psz = pDrvInfo6->pMonitorName;
  455. LPSTR pszStr;
  456. if ( psz && *psz ) {
  457. MonitorInfo2.pName = psz;
  458. MonitorInfo2.pEnvironment = NULL;
  459. MonitorInfo2.pDLLName = (LPWSTR) (psz+wcslen(psz)+1);
  460. //
  461. // Add is succesful, or monitor is already installed?
  462. //
  463. if ( AddMonitorW(NULL, 2, (LPBYTE) &MonitorInfo2) ||
  464. GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED ) {
  465. return TRUE;
  466. } else {
  467. if ( pszStr = ErrorMsg() ) {
  468. LogError(LogSevError, IDS_ADDMONITOR_FAILED,
  469. psz, pszStr);
  470. FreeMem(pszStr);
  471. }
  472. return FALSE;
  473. }
  474. }
  475. return TRUE;
  476. }
  477. VOID
  478. KeepAliveThread(
  479. HANDLE hRunning
  480. )
  481. /*++
  482. Routine Description:
  483. Printing migration may take a long time depending on number of printers and
  484. how long spooler takes to return. To inform setup that we are still alive
  485. I need to set a named event atleast once every 3 minutes
  486. Arguments:
  487. hRunning : When this gets closed we know processing is done
  488. Return Value:
  489. None
  490. --*/
  491. {
  492. //
  493. // Every 30 seconds set the global event telling we are still alive
  494. //
  495. do {
  496. SetEvent(hAlive);
  497. } while ( WAIT_TIMEOUT == WaitForSingleObject(hRunning, 1000*30) );
  498. CloseHandle(hAlive);
  499. hAlive = NULL;
  500. }
  501. VOID
  502. UpgradePrinterDrivers(
  503. IN PDRIVER_NODE pDriverNode,
  504. IN HDEVINFO hDevInfo,
  505. IN OUT LPBOOL pbFail
  506. )
  507. /*++
  508. Routine Description:
  509. Upgrades printer drivers by doing the file copy operations and calling
  510. AddPrinterDriver on spooler
  511. Arguments:
  512. pUpgradableDrvNode : List of drivers to upgrade
  513. pbFail : Set on an error -- no more processing needed
  514. Return Value:
  515. None
  516. --*/
  517. {
  518. BOOL bDriverToUpgrade = FALSE;
  519. LPWSTR pszDriverW, pszICMW;
  520. LPSTR pszDriverA, pszStr;
  521. PDRIVER_NODE pCur;
  522. DRIVER_FIELD DrvField;
  523. //
  524. // Set device install parameters so ntprint.dll will just queue up the
  525. // driver files and return without doing the copy. We will commit the
  526. // file queue at the end
  527. //
  528. if ( !InitFileCopyOnNT(hDevInfo) ) {
  529. *pbFail = TRUE;
  530. goto Cleanup;
  531. }
  532. //
  533. // Now for each printer driver call ntprint.dll to queue up the driver files
  534. // If it fails log an error
  535. //
  536. for ( pCur = pDriverNode ; pCur ; pCur = pCur->pNext ) {
  537. pszDriverA = pCur->DrvInfo1.pName;
  538. if ( (pszDriverW = AllocStrWFromStrA(pszDriverA)) &&
  539. (pCur->pLocalData = LAZYLOAD_INFO.pfnDriverInfoFromName(
  540. hDevInfo, (LPSTR)pszDriverW)) &&
  541. SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES,
  542. hDevInfo,
  543. NULL) ) {
  544. bDriverToUpgrade = TRUE;
  545. } else {
  546. pCur->bCantAdd = TRUE;
  547. }
  548. FreeMem(pszDriverW);
  549. }
  550. if ( !bDriverToUpgrade )
  551. goto Cleanup;
  552. #ifdef VERBOSE
  553. DebugMsg("Starting file copy ...");
  554. #endif
  555. //
  556. // Now commit the file queue to copy the files
  557. //
  558. if ( !CommitFileQueueToCopyFiles(hDevInfo) ) {
  559. *pbFail = TRUE;
  560. if ( pszStr = ErrorMsg() ) {
  561. LogError(LogSevError, IDS_DRIVERS_UPGRADE_FAILED, pszStr);
  562. FreeMem(pszStr);
  563. }
  564. goto Cleanup;
  565. }
  566. #ifdef VERBOSE
  567. DebugMsg("... files copied successfully");
  568. #endif
  569. //
  570. // Now call spooler to install the printer driver. Also install the
  571. // ICM profiles associated with the printer driver
  572. //
  573. for ( pCur = pDriverNode ; pCur ; pCur = pCur->pNext ) {
  574. //
  575. // We already logged an error if bCantAdd is TRUE
  576. //
  577. if ( pCur->bCantAdd )
  578. continue;
  579. DrvField.Index = DRV_INFO_6;
  580. DrvField.pDriverInfo4 = NULL;
  581. if ( !LAZYLOAD_INFO.pfnGetLocalDataField(pCur->pLocalData,
  582. PlatformX86,
  583. &DrvField) ||
  584. !CheckAndAddMonitor((LPDRIVER_INFO_6W) DrvField.pDriverInfo6) ||
  585. !AddPrinterDriverW(NULL,
  586. 6,
  587. (LPBYTE)DrvField.pDriverInfo6) ) {
  588. if ( pszStr = ErrorMsg() ) {
  589. LogError(LogSevError, IDS_ADDDRIVER_FAILED, pCur->DrvInfo1.pName, pszStr);
  590. FreeMem(pszStr);
  591. }
  592. }
  593. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  594. DrvField.Index = ICM_FILES;
  595. DrvField.pszzICMFiles = NULL;
  596. if ( !LAZYLOAD_INFO.pfnGetLocalDataField(pCur->pLocalData,
  597. PlatformX86,
  598. &DrvField) ) {
  599. continue;
  600. }
  601. if ( DrvField.pszzICMFiles )
  602. LAZYLOAD_INFO.pfnInstallICMProfiles(NULL,
  603. DrvField.pszzICMFiles);
  604. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  605. }
  606. Cleanup:
  607. return;
  608. }
  609. PSECURITY_DESCRIPTOR
  610. GetSecurityDescriptor(
  611. IN LPCSTR pszUser
  612. )
  613. /*++
  614. Routine Description:
  615. Get the users security
  616. Arguments:
  617. pszUser : sub key under HKEY_USER
  618. Return Value:
  619. NULL on error, else a valid SECURITY_DESCRIPTOR.
  620. Memory is allocated in the heap and caller should free it.
  621. --*/
  622. {
  623. HKEY hKey = NULL;
  624. DWORD dwSize;
  625. PSECURITY_DESCRIPTOR pSD = NULL;
  626. if ( RegOpenKeyExA(HKEY_USERS,
  627. pszUser,
  628. 0,
  629. KEY_READ|KEY_WRITE,
  630. &hKey) ||
  631. RegGetKeySecurity(hKey,
  632. DACL_SECURITY_INFORMATION,
  633. NULL,
  634. &dwSize) != ERROR_INSUFFICIENT_BUFFER ||
  635. !(pSD = (PSECURITY_DESCRIPTOR) AllocMem(dwSize)) ||
  636. RegGetKeySecurity(hKey,
  637. DACL_SECURITY_INFORMATION,
  638. pSD,
  639. &dwSize) ) {
  640. if ( hKey )
  641. RegCloseKey(hKey);
  642. FreeMem(pSD);
  643. pSD = NULL;
  644. }
  645. return pSD;
  646. }
  647. typedef BOOL (WINAPI *P_XCV_DATA_W)(
  648. IN HANDLE hXcv,
  649. IN PCWSTR pszDataName,
  650. IN PBYTE pInputData,
  651. IN DWORD cbInputData,
  652. OUT PBYTE pOutputData,
  653. IN DWORD cbOutputData,
  654. OUT PDWORD pcbOutputNeeded,
  655. OUT PDWORD pdwStatus
  656. );
  657. BOOL
  658. AddLocalPort(
  659. IN LPSTR pPortName
  660. )
  661. /*++
  662. Routine Description:
  663. Adds a local port
  664. Arguments:
  665. pPortName : Name of the local port to add
  666. Return Value:
  667. FALSE if a port can't be added.
  668. --*/
  669. {
  670. PRINTER_DEFAULTS PrinterDefault = {NULL, NULL, SERVER_ACCESS_ADMINISTER};
  671. HANDLE hXcvMon = NULL;
  672. BOOL bReturn = FALSE;
  673. if (OpenPrinterA(",XcvMonitor Local Port", &hXcvMon, &PrinterDefault))
  674. {
  675. DWORD cbOutputNeeded = 0;
  676. DWORD Status = NO_ERROR;
  677. WCHAR *pUnicodePortName = NULL;
  678. P_XCV_DATA_W pXcvData = NULL;
  679. HMODULE hWinSpool = NULL;
  680. //
  681. // if I implib-link to XcvData, loading the migrate.dll on Win9x will fail !
  682. //
  683. hWinSpool = LoadLibraryUsingFullPathA("winspool.drv");
  684. if (!hWinSpool)
  685. {
  686. DebugMsg("LoadLibrary on winspool.drv failed");
  687. goto Done;
  688. }
  689. pXcvData = (P_XCV_DATA_W) GetProcAddress(hWinSpool, "XcvDataW");
  690. if (!pXcvData)
  691. {
  692. DebugMsg("GetProcAddress on winspool.drv failed");
  693. goto Done;
  694. }
  695. pUnicodePortName = AllocStrWFromStrA(pPortName);
  696. if (pUnicodePortName)
  697. {
  698. bReturn = (*pXcvData)(hXcvMon,
  699. L"AddPort",
  700. (LPBYTE) pUnicodePortName,
  701. (wcslen(pUnicodePortName) +1) * sizeof(WCHAR),
  702. NULL,
  703. 0,
  704. &cbOutputNeeded,
  705. &Status
  706. );
  707. FreeMem(pUnicodePortName);
  708. }
  709. Done:
  710. if (hWinSpool)
  711. {
  712. FreeLibrary(hWinSpool);
  713. }
  714. ClosePrinter(hXcvMon);
  715. }
  716. return bReturn;
  717. }
  718. VOID
  719. UpgradePrinters(
  720. IN PPRINTER_NODE pPrinterNode,
  721. IN PDRIVER_NODE pDriverNode,
  722. IN PPORT_NODE *ppPortNode,
  723. IN HDEVINFO hDevInfo
  724. )
  725. /*++
  726. Routine Description:
  727. Upgrade printers on NT
  728. Arguments:
  729. pPrinterNode : Gives the list giving information about the printers
  730. which existed on Win9x
  731. Return Value:
  732. None
  733. --*/
  734. {
  735. DWORD dwLen, dwLastError;
  736. LPSTR pszStr, pszPrinterNameA;
  737. LPWSTR pszPrinterNameW;
  738. HANDLE hPrinter;
  739. DRIVER_FIELD DrvField;
  740. PPSETUP_LOCAL_DATA pLocalData;
  741. PPORT_NODE pCurPort, pPrevPort = NULL;
  742. DWORD dwSize;
  743. LPSTR pszVendorSetupA = NULL;
  744. for ( ; pPrinterNode ; pPrinterNode = pPrinterNode->pNext ) {
  745. pszPrinterNameA = pPrinterNode->PrinterInfo2.pPrinterName;
  746. //
  747. // check whether this printer uses a non-standard local file port
  748. //
  749. for (pCurPort = *ppPortNode; pCurPort != NULL; pPrevPort = pCurPort, pCurPort = pCurPort->pNext)
  750. {
  751. if (lstrcmpi(pPrinterNode->PrinterInfo2.pPortName, pCurPort->pPortName) == 0)
  752. {
  753. //
  754. // Create the port
  755. //
  756. AddLocalPort(pCurPort->pPortName);
  757. //
  758. // remove it from the list
  759. //
  760. if (pCurPort == *ppPortNode)
  761. {
  762. *ppPortNode = pCurPort->pNext;
  763. }
  764. else
  765. {
  766. pPrevPort->pNext = pCurPort->pNext;
  767. }
  768. FreePortNode(pCurPort);
  769. break;
  770. }
  771. }
  772. hPrinter = AddPrinterA(NULL,
  773. 2,
  774. (LPBYTE)&pPrinterNode->PrinterInfo2);
  775. if ( !hPrinter ) {
  776. dwLastError = GetLastError();
  777. //
  778. // If driver is unknown we already logged warned the user
  779. // If printer already exists it is ok (for Fax printer this is true)
  780. //
  781. if ( dwLastError != ERROR_UNKNOWN_PRINTER_DRIVER &&
  782. dwLastError != ERROR_INVALID_PRINTER_NAME &&
  783. dwLastError != ERROR_PRINTER_ALREADY_EXISTS &&
  784. (pszStr = ErrorMsg()) ) {
  785. LogError(LogSevError,
  786. IDS_ADDPRINTER_FAILED,
  787. pszPrinterNameA,
  788. pszStr);
  789. FreeMem(pszStr);
  790. }
  791. continue;
  792. }
  793. pLocalData = FindLocalDataForDriver(pDriverNode,
  794. pPrinterNode->PrinterInfo2.pDriverName);
  795. pszPrinterNameW = AllocStrWFromStrA(pszPrinterNameA);
  796. if ( pLocalData && pszPrinterNameW ) {
  797. DrvField.Index = ICM_FILES;
  798. DrvField.pszzICMFiles = NULL;
  799. if ( LAZYLOAD_INFO.pfnGetLocalDataField(pLocalData,
  800. PlatformX86,
  801. &DrvField) ) {
  802. if ( DrvField.pszzICMFiles )
  803. LAZYLOAD_INFO.pfnAssociateICMProfiles(
  804. (LPTSTR)pszPrinterNameW,
  805. DrvField.pszzICMFiles);
  806. LAZYLOAD_INFO.pfnFreeDrvField(&DrvField);
  807. }
  808. LAZYLOAD_INFO.pfnProcessPrinterAdded(hDevInfo,
  809. pLocalData,
  810. (LPTSTR)pszPrinterNameW,
  811. INVALID_HANDLE_VALUE);
  812. dwSize = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)(pLocalData->InfInfo.pszVendorSetup),
  813. -1, NULL, 0, NULL, NULL);
  814. if (dwSize > 0)
  815. {
  816. pszVendorSetupA = (LPSTR)AllocMem( dwSize );
  817. if (pszVendorSetupA)
  818. {
  819. if (WideCharToMultiByte (CP_ACP, 0, (LPCWSTR)(pLocalData->InfInfo.pszVendorSetup),
  820. -1, pszVendorSetupA, dwSize, NULL, NULL))
  821. {
  822. WriteVendorSetupInfoInRegistry( pszVendorSetupA, pszPrinterNameA );
  823. }
  824. FreeMem( pszVendorSetupA );
  825. }
  826. }
  827. }
  828. //
  829. // Default printer will be the one with PRINTER_ATTRIBUTE_DEFAULT attribute
  830. // If the Win95 default printer could not be added to NT we will set the
  831. // first printer as the default printer
  832. //
  833. if ( (pPrinterNode->PrinterInfo2.Attributes
  834. & PRINTER_ATTRIBUTE_DEFAULT) ||
  835. !pDefPrinter )
  836. pDefPrinter = pPrinterNode;
  837. FreeMem(pszPrinterNameW);
  838. ClosePrinter(hPrinter);
  839. }
  840. if ( pDefPrinter )
  841. pszDefaultPrinterString = GetDefPrnString(
  842. pDefPrinter->PrinterInfo2.pPrinterName);
  843. }
  844. HDEVINFO
  845. PrinterDevInfo(
  846. IN OUT LPBOOL pbFail
  847. )
  848. /*++
  849. --*/
  850. {
  851. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  852. if ( *pbFail || !InitLazyLoadInfo() ) {
  853. *pbFail = TRUE;
  854. goto Cleanup;
  855. }
  856. hDevInfo = LAZYLOAD_INFO.pfnCreatePrinterDeviceInfoList(INVALID_HANDLE_VALUE);
  857. if ( hDevInfo == INVALID_HANDLE_VALUE ||
  858. !LAZYLOAD_INFO.pfnBuildDriversFromPath(hDevInfo,
  859. (LPSTR)L"ntprint.inf",
  860. TRUE) ) {
  861. *pbFail = TRUE;
  862. goto Cleanup;
  863. }
  864. #ifdef VERBOSE
  865. DebugMsg("Built the list of printer drivers from ntprint.inf");
  866. #endif
  867. if ( *pbFail && hDevInfo != INVALID_HANDLE_VALUE ) {
  868. LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList(hDevInfo);
  869. hDevInfo = INVALID_HANDLE_VALUE;
  870. }
  871. Cleanup:
  872. return hDevInfo;
  873. }
  874. LONG
  875. CALLBACK
  876. InitializeNT(
  877. IN LPCWSTR pszWorkingDir,
  878. IN LPCWSTR pszSourceDir,
  879. LPVOID Reserved
  880. )
  881. /*++
  882. Routine Description:
  883. Setup calls this to intialize us on NT side
  884. Arguments:
  885. pszWorkingDir : Gives the working directory assigned for printing
  886. pszSourceDir : Source location for NT distribution files
  887. Reserved : Leave it alone
  888. Return Value:
  889. Win32 error code
  890. --*/
  891. {
  892. BOOL bFail = FALSE;
  893. DWORD dwReturn, ThreadId;
  894. HANDLE hRunning = NULL, hThread;
  895. HDSKSPC DiskSpace;
  896. LPSTR pszStr;
  897. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  898. PDRIVER_NODE pDriverNode = NULL;
  899. PPRINTER_NODE pPrinterNode = NULL;
  900. PPORT_NODE pPortNode = NULL;
  901. #ifdef VERBOSE
  902. DebugMsg("InitializeNT : %ws, %ws", pszSourceDir, pszWorkingDir);
  903. #endif
  904. UpgradeData.pszDir = AllocStrAFromStrW(pszWorkingDir);
  905. UpgradeData.pszSourceW = AllocStrW(pszSourceDir);
  906. UpgradeData.pszSourceA = AllocStrAFromStrW(pszSourceDir);
  907. if ( !UpgradeData.pszDir ||
  908. !UpgradeData.pszSourceW ||
  909. !UpgradeData.pszSourceA ) {
  910. return GetLastError();
  911. }
  912. if ( (hAlive = OpenEventA(EVENT_MODIFY_STATE, FALSE, "MigDllAlive")) &&
  913. (hRunning = CreateEventA(NULL, FALSE, FALSE, NULL)) &&
  914. (hThread = CreateThread(NULL, 0,
  915. (LPTHREAD_START_ROUTINE)KeepAliveThread,
  916. hRunning,
  917. 0, &ThreadId)) )
  918. CloseHandle(hThread);
  919. SetupOpenLog(FALSE);
  920. DeleteWin95Files();
  921. if ( !ReadWin9xPrintConfig(&pDriverNode, &pPrinterNode, &pPortNode) ) {
  922. bFail = TRUE;
  923. DebugMsg("Unable to read Windows 9x printing configuration");
  924. goto Cleanup;
  925. }
  926. #ifdef VERBOSE
  927. DebugMsg("Succesfully read Windows 9x printing configuration");
  928. #endif
  929. //
  930. // If no printers or drivers found nothing to do
  931. //
  932. if ( !pDriverNode && !pPrinterNode )
  933. goto Cleanup;
  934. if ( (hDevInfo = PrinterDevInfo(&bFail)) == INVALID_HANDLE_VALUE )
  935. goto Cleanup;
  936. UpgradePrinterDrivers(pDriverNode, hDevInfo, &bFail);
  937. UpgradePrinters(pPrinterNode, pDriverNode, &pPortNode, hDevInfo);
  938. MakeACopyOfMigrateDll( UpgradeData.pszDir );
  939. Cleanup:
  940. SetupCloseLog();
  941. if ( bFail && (pszStr = ErrorMsg()) ) {
  942. DebugMsg("Printing migration failed. %s", pszStr);
  943. FreeMem(pszStr);
  944. }
  945. FreePrinterNodeList(pPrinterNode);
  946. FreeDriverNodeList(pDriverNode);
  947. FreePortNodeList(pPortNode);
  948. if ( hDevInfo != INVALID_HANDLE_VALUE )
  949. LAZYLOAD_INFO.pfnDestroyPrinterDeviceInfoList(hDevInfo);
  950. if ( LAZYLOAD_INFO.hNtPrint )
  951. FreeLibrary(LAZYLOAD_INFO.hNtPrint);
  952. if ( bFail ) {
  953. if ( (dwReturn = GetLastError()) == ERROR_SUCCESS ) {
  954. ASSERT(dwReturn != ERROR_SUCCESS);
  955. dwReturn = STG_E_UNKNOWN;
  956. }
  957. } else {
  958. SetupNetworkPrinterUpgrade(UpgradeData.pszDir);
  959. dwReturn = ERROR_SUCCESS;
  960. #ifdef VERBOSE
  961. DebugMsg("InitializeNT returning success");
  962. #endif
  963. }
  964. if ( hRunning )
  965. CloseHandle(hRunning);
  966. while (hAlive)
  967. Sleep(100); // Check after 0.1 second for the main thread to die
  968. return dwReturn;
  969. }
  970. DWORD
  971. MySetDefaultPrinter(
  972. IN HKEY hUserRegKey,
  973. IN LPSTR pszDefaultPrinterString
  974. )
  975. /*++
  976. Routine Description:
  977. Sets the default printer for the user by writing it to the registry
  978. Arguments:
  979. Return Value:
  980. --*/
  981. {
  982. DWORD dwReturn;
  983. HKEY hKey = NULL;
  984. //
  985. // Create the printers key in the user hive and write DeviceOld value
  986. //
  987. dwReturn = RegCreateKeyExA(hUserRegKey,
  988. "Printers",
  989. 0,
  990. NULL,
  991. 0,
  992. KEY_ALL_ACCESS,
  993. NULL,
  994. &hKey,
  995. NULL);
  996. if ( dwReturn == ERROR_SUCCESS ) {
  997. dwReturn = RegSetValueExA(hKey,
  998. "DeviceOld",
  999. 0,
  1000. REG_SZ,
  1001. (LPBYTE)pszDefaultPrinterString,
  1002. (strlen(pszDefaultPrinterString) + 1)
  1003. * sizeof(CHAR));
  1004. RegCloseKey(hKey);
  1005. }
  1006. return dwReturn;
  1007. }
  1008. LONG
  1009. CALLBACK
  1010. MigrateUserNT(
  1011. IN HINF hUnattendInf,
  1012. IN HKEY hUserRegKey,
  1013. IN LPCWSTR pszUserName,
  1014. LPVOID Reserved
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. Migrate user settings
  1019. Arguments:
  1020. Return Value:
  1021. --*/
  1022. {
  1023. LPSTR pszStr;
  1024. DWORD dwReturn = ERROR_SUCCESS;
  1025. #ifdef VERBOSE
  1026. DebugMsg("Migrating settings for %ws", pszUserName);
  1027. #endif
  1028. if ( pszDefaultPrinterString ) {
  1029. dwReturn = MySetDefaultPrinter(hUserRegKey,
  1030. pszDefaultPrinterString);
  1031. if ( dwReturn )
  1032. DebugMsg("MySetDefaultPrinter failed with %d", dwReturn);
  1033. }
  1034. if ( bDoNetPrnUpgrade ) {
  1035. if ( ProcessNetPrnUpgradeForUser(hUserRegKey) )
  1036. ++dwRunOnceCount;
  1037. else {
  1038. if ( dwReturn == ERROR_SUCCESS )
  1039. dwReturn = GetLastError();
  1040. DebugMsg("ProcessNetPrnUpgradeForUser failed with %d", dwReturn);
  1041. }
  1042. }
  1043. #ifdef VERBOSE
  1044. if ( dwReturn )
  1045. DebugMsg("MigrateUserNT failed with %d", dwReturn);
  1046. else
  1047. DebugMsg("MigrateUserNT succesful");
  1048. #endif
  1049. return dwReturn;
  1050. }
  1051. LONG
  1052. CALLBACK
  1053. MigrateSystemNT(
  1054. IN HINF hUnattendInf,
  1055. LPVOID Reserved
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. Process system setttings for printing. All the printing setting are
  1060. migrated in InitializeNT since we need to know the default printer for
  1061. each user in the MigrateSystemNT call
  1062. Arguments:
  1063. hUnattendInf : Handle to the unattended INF
  1064. Return Value:
  1065. Win32 error code
  1066. --*/
  1067. {
  1068. WriteRunOnceCount();
  1069. return ERROR_SUCCESS;
  1070. }
  1071. //
  1072. // The following are to make sure if setup changes the header file they
  1073. // first tell me (otherwise they will break build of this)
  1074. //
  1075. P_INITIALIZE_NT pfnInitializeNT = InitializeNT;
  1076. P_MIGRATE_USER_NT pfnMigrateUserNt = MigrateUserNT;
  1077. P_MIGRATE_SYSTEM_NT pfnMigrateSystemNT = MigrateSystemNT;