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.

1044 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. printer.c
  5. Abstract:
  6. This file implements the printer/spooler code.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include "wizard.h"
  13. #pragma hdrstop
  14. TCHAR Environment[MAX_PATH];
  15. TCHAR DataFile[MAX_PATH];
  16. TCHAR ConfigFile[MAX_PATH];
  17. TCHAR DriverFile[MAX_PATH];
  18. TCHAR MonitorFile[MAX_PATH];
  19. TCHAR PrinterName[MAX_PATH];
  20. TCHAR DriverDirectory[MAX_PATH];
  21. DRIVER_INFO_2 DriverInfo =
  22. {
  23. 2, // cVersion
  24. FAX_DRIVER_NAME, // pName
  25. Environment, // pEnvironment
  26. DriverFile, // pDriverPath
  27. DataFile, // pDataFile
  28. ConfigFile // pConfigFile
  29. };
  30. PRINTER_INFO_2 PrinterInfo =
  31. {
  32. NULL, // pServerName
  33. PrinterName, // pPrinterName
  34. NULL, // pShareName
  35. NULL, // pPortName
  36. FAX_DRIVER_NAME, // pDriverName
  37. NULL, // pComment
  38. NULL, // pLocation
  39. NULL, // pDevMode
  40. NULL, // pSepFile
  41. TEXT("winprint"), // pPrintProcessor
  42. TEXT("RAW"), // pDatatype
  43. NULL, // pParameters
  44. NULL, // pSecurityDescriptor
  45. 0, // Attributes
  46. 0, // Priority
  47. 0, // DefaultPriority
  48. 0, // StartTime
  49. 0, // UntilTime
  50. 0, // Status
  51. 0, // cJobs
  52. 0 // AveragePPM
  53. };
  54. MONITOR_INFO_2 MonitorInfo =
  55. {
  56. FAX_MONITOR_NAME, // pName
  57. Environment, // pEnvironment
  58. MonitorFile // pDLLName
  59. };
  60. BOOL
  61. AddPrinterDrivers(
  62. VOID
  63. )
  64. {
  65. DWORD i;
  66. DWORD BytesNeeded;
  67. for (i=0; i<MAX_PLATFORMS; i++) {
  68. if (!Platforms[i].Selected) {
  69. continue;
  70. }
  71. _tcscpy( Environment, Platforms[i].PrintPlatform );
  72. if (!GetPrinterDriverDirectory(
  73. NULL,
  74. Environment,
  75. 1,
  76. (LPBYTE) DriverDirectory,
  77. sizeof(DriverDirectory),
  78. &BytesNeeded
  79. )) {
  80. DebugPrint(( TEXT("GetPrinterDriverDirectory() failed, ec=%d"), GetLastError() ));
  81. return FALSE;
  82. }
  83. //
  84. // form the file names
  85. //
  86. _tcscpy( DriverFile, DriverDirectory );
  87. _tcscat( DriverFile, TEXT("\\faxdrv.dll") );
  88. _tcscpy( DataFile, DriverDirectory );
  89. _tcscat( DataFile, TEXT("\\faxwiz.dll") );
  90. _tcscpy( ConfigFile, DriverDirectory );
  91. _tcscat( ConfigFile, TEXT("\\faxui.dll") );
  92. if ((!AddPrinterDriver( NULL, 2, (LPBYTE) &DriverInfo )) &&
  93. (GetLastError() != ERROR_PRINTER_DRIVER_ALREADY_INSTALLED)) {
  94. DebugPrint(( TEXT("AddPrinterDriver() failed, ec=%d"), GetLastError() ));
  95. return FALSE;
  96. }
  97. }
  98. return TRUE;
  99. }
  100. BOOL
  101. SetDefaultPrinter(
  102. LPTSTR PrinterName,
  103. BOOL OverwriteDefaultPrinter
  104. )
  105. {
  106. HKEY hKey;
  107. LPTSTR PrinterInfo;
  108. LPTSTR DefaultPrinter;
  109. BOOL Rslt;
  110. if (!OverwriteDefaultPrinter) {
  111. //
  112. // check to see if there is a printer
  113. // marked as the default ptinter
  114. //
  115. hKey = OpenRegistryKey(
  116. HKEY_CURRENT_USER,
  117. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"),
  118. FALSE,
  119. KEY_READ
  120. );
  121. if (hKey == NULL) {
  122. return FALSE;
  123. }
  124. DefaultPrinter = GetRegistryString( hKey, TEXT("Device"), EMPTY_STRING );
  125. RegCloseKey( hKey );
  126. if (DefaultPrinter && DefaultPrinter[0]) {
  127. MemFree( DefaultPrinter );
  128. return FALSE;
  129. }
  130. //
  131. // ok, there is not a default printer
  132. // and we can proceed
  133. //
  134. MemFree( DefaultPrinter );
  135. }
  136. //
  137. // get the printer information for the requested printer
  138. //
  139. hKey = OpenRegistryKey(
  140. HKEY_CURRENT_USER,
  141. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices"),
  142. FALSE,
  143. KEY_READ
  144. );
  145. if (hKey == NULL) {
  146. return FALSE;
  147. }
  148. PrinterInfo = GetRegistryString( hKey, PrinterName, EMPTY_STRING );
  149. RegCloseKey( hKey );
  150. if (PrinterInfo == NULL || PrinterInfo[0] == 0) {
  151. MemFree( PrinterInfo );
  152. return FALSE;
  153. }
  154. DefaultPrinter = MemAlloc( (_tcslen(PrinterName) + _tcslen(PrinterInfo) + 16) * sizeof(TCHAR) );
  155. if (!DefaultPrinter) {
  156. MemFree( PrinterInfo );
  157. return FALSE;
  158. }
  159. _tcscpy( DefaultPrinter, PrinterName );
  160. _tcscat( DefaultPrinter, TEXT(",") );
  161. _tcscat( DefaultPrinter, PrinterInfo );
  162. MemFree( PrinterInfo );
  163. hKey = OpenRegistryKey(
  164. HKEY_CURRENT_USER,
  165. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"),
  166. FALSE,
  167. KEY_ALL_ACCESS
  168. );
  169. if (hKey == NULL) {
  170. MemFree( DefaultPrinter );
  171. return FALSE;
  172. }
  173. Rslt = SetRegistryString( hKey, TEXT("Device"), DefaultPrinter );
  174. RegCloseKey( hKey );
  175. MemFree( DefaultPrinter );
  176. return Rslt;
  177. }
  178. BOOL
  179. CreateServerFaxPrinter(
  180. HWND hwnd,
  181. LPTSTR FaxPrinterName
  182. )
  183. {
  184. HANDLE hPrinter;
  185. SYSTEM_INFO SystemInfo;
  186. DWORD BytesNeeded;
  187. DWORD PortCount;
  188. PORT_INFO_2 *PortInfo = NULL;
  189. DWORD i;
  190. LPTSTR PortNames = NULL;
  191. LPTSTR p;
  192. PRINTER_DEFAULTS PrinterDefaults;
  193. //
  194. // set the printer name
  195. //
  196. _tcscpy( PrinterName, FaxPrinterName );
  197. //
  198. // add the fax port monitor
  199. // the fax ports that the fax monitor presents
  200. // to the spooler are dynamic. they are ctreated
  201. // at the time the monitor initializes. the ports
  202. // are created based on data that the monitor
  203. // gets from the fax service when it calls FaxEnumPorts().
  204. //
  205. GetSystemInfo( &SystemInfo );
  206. if ( (SystemInfo.wProcessorArchitecture > 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM ) ) {
  207. return FALSE;
  208. }
  209. _tcscpy( Environment, Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform );
  210. _tcscpy( MonitorFile, TEXT("faxmon.dll") );
  211. if ((!AddMonitor( NULL, 2, (LPBYTE) &MonitorInfo )) &&
  212. (GetLastError() != ERROR_PRINT_MONITOR_ALREADY_INSTALLED)) {
  213. DebugPrint(( TEXT("AddMonitor() failed, ec=%d"), GetLastError() ));
  214. return FALSE;
  215. }
  216. //
  217. // enumerate the ports so we can isolate the fax ports
  218. //
  219. if ((!EnumPorts( NULL, 2, NULL, 0, &BytesNeeded, &PortCount )) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  220. PortInfo = (PORT_INFO_2 *) MemAlloc( BytesNeeded );
  221. if (PortInfo) {
  222. if (EnumPorts( NULL, 2, (LPBYTE)PortInfo, BytesNeeded, &BytesNeeded, &PortCount )) {
  223. for (BytesNeeded=0,i=0; i<PortCount; i++) {
  224. if (PortInfo[i].pMonitorName && (_tcscmp( PortInfo[i].pMonitorName, FAX_MONITOR_NAME ) == 0)) {
  225. BytesNeeded += _tcslen( PortInfo[i].pPortName ) + 4;
  226. }
  227. }
  228. if (!BytesNeeded) {
  229. //
  230. // there are no fax ports available
  231. //
  232. DebugPrint(( TEXT("There are no FAX ports available") ));
  233. return FALSE;
  234. }
  235. PortNames = (LPTSTR) MemAlloc( (BytesNeeded + 16) * sizeof(TCHAR) );
  236. if (PortNames) {
  237. p = PortNames;
  238. for (p=PortNames,i=0; i<PortCount; i++) {
  239. if (PortInfo[i].pMonitorName && (_tcscmp( PortInfo[i].pMonitorName, FAX_MONITOR_NAME ) == 0)) {
  240. _tcscpy( p, PortInfo[i].pPortName );
  241. _tcscat( p, TEXT(",") );
  242. p += _tcslen( p );
  243. }
  244. }
  245. *(p-1) = 0;
  246. PrinterInfo.pPortName = PortNames;
  247. }
  248. }
  249. }
  250. }
  251. if (!PrinterInfo.pPortName) {
  252. //
  253. // there are no fax ports available
  254. //
  255. DebugPrint(( TEXT("There are no FAX ports available") ));
  256. return FALSE;
  257. }
  258. if (!AddPrinterDrivers()) {
  259. return FALSE;
  260. }
  261. //
  262. // add the printer, open it if it already exists
  263. //
  264. hPrinter = AddPrinter( NULL, 2, (LPBYTE) &PrinterInfo );
  265. if (!hPrinter) {
  266. if (GetLastError() == ERROR_PRINTER_ALREADY_EXISTS) {
  267. PrinterDefaults.pDatatype = NULL;
  268. PrinterDefaults.pDevMode = NULL;
  269. PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS;
  270. if (!OpenPrinter( FaxPrinterName, &hPrinter, &PrinterDefaults )) {
  271. DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() ));
  272. return FALSE;
  273. }
  274. } else {
  275. DebugPrint(( TEXT("AddPrinter() failed, ec=%d"), GetLastError() ));
  276. return FALSE;
  277. }
  278. }
  279. //
  280. // share the printer
  281. //
  282. if (!ShareFaxPrinter( &hPrinter, FaxPrinterName )) {
  283. DebugPrint(( TEXT("ShareFaxPrinter() failed") ));
  284. if (!NtGuiMode) {
  285. PopUpMsg( hwnd, IDS_SHARE_FAX_PRINTER, FALSE, 0 );
  286. }
  287. }
  288. //
  289. // make the fax printer the default printer, if it is the only printer
  290. //
  291. SetDefaultPrinter( FaxPrinterName, FALSE );
  292. //
  293. // set the bit that allow status strings to display correctly
  294. //
  295. i = 1;
  296. i = SetPrinterData(
  297. hPrinter,
  298. SPLREG_UI_SINGLE_STATUS,
  299. REG_DWORD,
  300. (LPBYTE) &i,
  301. sizeof(DWORD)
  302. );
  303. if ((i != ERROR_SUCCESS) && (i != ERROR_SUCCESS_RESTART_REQUIRED)) {
  304. DebugPrint(( TEXT("SetPrinterData() failed, ec=%d"), i ));
  305. return FALSE;
  306. }
  307. //
  308. // release resources and leave...
  309. //
  310. MemFree( PortNames );
  311. MemFree( PortInfo );
  312. ClosePrinter( hPrinter );
  313. return TRUE;
  314. }
  315. DWORD
  316. CreateClientFaxPrinter(
  317. HWND hwnd,
  318. LPTSTR FaxPrinterName
  319. )
  320. {
  321. DWORD ec = ERROR_SUCCESS;
  322. SYSTEM_INFO SystemInfo;
  323. DWORD i;
  324. GetSystemInfo( &SystemInfo );
  325. if ((SystemInfo.wProcessorArchitecture > 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM)) {
  326. return ERROR_INVALID_FUNCTION;
  327. }
  328. _tcscpy( Environment, Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform );
  329. if (!GetPrinterDriverDirectory(
  330. NULL,
  331. Environment,
  332. 1,
  333. (LPBYTE) DriverDirectory,
  334. sizeof(DriverDirectory),
  335. &i
  336. )) {
  337. ec = GetLastError();
  338. DebugPrint(( TEXT("GetPrinterDriverDirectory() failed, ec=%d"), ec ));
  339. return ec;
  340. }
  341. //
  342. // form the file names
  343. //
  344. _tcscpy( DriverFile, DriverDirectory );
  345. _tcscat( DriverFile, TEXT("\\faxdrv.dll") );
  346. _tcscpy( DataFile, DriverDirectory );
  347. _tcscat( DataFile, TEXT("\\faxwiz.dll") );
  348. _tcscpy( ConfigFile, DriverDirectory );
  349. _tcscat( ConfigFile, TEXT("\\faxui.dll") );
  350. if ((!AddPrinterDriver( NULL, 2, (LPBYTE) &DriverInfo )) &&
  351. (GetLastError() != ERROR_PRINTER_DRIVER_ALREADY_INSTALLED)) {
  352. ec = GetLastError();
  353. DebugPrint(( TEXT("AddPrinterDriver() failed, ec=%d"), GetLastError() ));
  354. return ec;
  355. }
  356. //
  357. // add the printer
  358. //
  359. add_printer_connection:
  360. if (!AddPrinterConnection( FaxPrinterName )) {
  361. i = GetLastError();
  362. if (i == ERROR_INVALID_PRINTER_NAME) {
  363. int DlgErr = DialogBoxParam(
  364. FaxWizModuleHandle,
  365. MAKEINTRESOURCE(IDD_PRINTER_NAME),
  366. hwnd,
  367. PrinterNameDlgProc,
  368. (LPARAM) FaxPrinterName
  369. );
  370. if (DlgErr == -1 || DlgErr == 0) {
  371. DebugPrint(( TEXT("PrinterNameDlgProc() failed or was cancelled") ));
  372. return ERROR_INVALID_FUNCTION;
  373. }
  374. if (!AddPrinterConnection( FaxPrinterName )) {
  375. DebugPrint(( TEXT("AddPrinterConnection() failed, ec=%d"), i ));
  376. goto add_printer_connection;
  377. }
  378. } else {
  379. DebugPrint(( TEXT("AddPrinterConnection() failed, ec=%d"), i ));
  380. return i;
  381. }
  382. }
  383. //
  384. // make the fax printer the default printer, if it is the only printer
  385. //
  386. SetDefaultPrinter( FaxPrinterName, FALSE);
  387. return ERROR_SUCCESS;
  388. }
  389. BOOL
  390. IsPrinterFaxPrinter(
  391. LPTSTR PrinterName
  392. )
  393. {
  394. HANDLE hPrinter = NULL;
  395. PRINTER_DEFAULTS PrinterDefaults;
  396. SYSTEM_INFO SystemInfo;
  397. DWORD Size;
  398. DWORD Rval = FALSE;
  399. LPDRIVER_INFO_2 DriverInfo = NULL;
  400. PrinterDefaults.pDatatype = NULL;
  401. PrinterDefaults.pDevMode = NULL;
  402. PrinterDefaults.DesiredAccess = PRINTER_READ;
  403. if (!OpenPrinter( PrinterName, &hPrinter, &PrinterDefaults )) {
  404. DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() ));
  405. return FALSE;
  406. }
  407. GetSystemInfo( &SystemInfo );
  408. Size = 4096;
  409. DriverInfo = (LPDRIVER_INFO_2) MemAlloc( Size );
  410. if (!DriverInfo) {
  411. DebugPrint(( TEXT("Memory allocation failed, size=%d"), Size ));
  412. goto exit;
  413. }
  414. if ( (SystemInfo.wProcessorArchitecture > 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM ) ) {
  415. return FALSE;
  416. }
  417. Rval = GetPrinterDriver(
  418. hPrinter,
  419. Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform,
  420. 2,
  421. (LPBYTE) DriverInfo,
  422. Size,
  423. &Size
  424. );
  425. if (!Rval) {
  426. DebugPrint(( TEXT("GetPrinterDriver() failed, ec=%d"), GetLastError() ));
  427. goto exit;
  428. }
  429. if (_tcscmp( DriverInfo->pName, FAX_DRIVER_NAME ) == 0) {
  430. Rval = TRUE;
  431. } else {
  432. Rval = FALSE;
  433. }
  434. exit:
  435. MemFree( DriverInfo );
  436. ClosePrinter( hPrinter );
  437. return Rval;
  438. }
  439. LPTSTR
  440. MakePrinterShareName(
  441. LPTSTR pServerName,
  442. LPTSTR pPrinterName
  443. )
  444. /*++
  445. Routine Description:
  446. Given a server name and a printer name, generate a unique share name.
  447. Arguments:
  448. pServerName - Specifies the server name, NULL for local host
  449. pPrinterName - Specifies the printer name
  450. Return Value:
  451. Pointer to the generated share name, NULL if there is an error
  452. --*/
  453. {
  454. static TCHAR illegalDosChars[] = TEXT( " *?/\\|,;:+=<>[]\"" );
  455. TCHAR shareName[16];
  456. INT cch, shareSuffix;
  457. DWORD dwFlags, cPrinters, index;
  458. LPTSTR pDest, pShareName;
  459. PPRINTER_INFO_2 pPrinterInfo2;
  460. //
  461. // Copy up to the first 8 characters of the printer name
  462. //
  463. ZeroMemory( shareName, sizeof(shareName) );
  464. pDest = shareName;
  465. cch = 0;
  466. while (cch < 8 && *pPrinterName) {
  467. //
  468. // Skip invalid DOS filename characters
  469. //
  470. if (!_tcschr( illegalDosChars, *pPrinterName )) {
  471. *pDest++ = *pPrinterName;
  472. cch++;
  473. }
  474. pPrinterName++;
  475. }
  476. //
  477. // If the share name is empty, start with a default.
  478. // This should very rarely happen.
  479. //
  480. if (cch == 0) {
  481. _tcscpy( shareName, GetString( IDS_DEFAULT_SHARE ) );
  482. pDest += _tcslen(pDest);
  483. }
  484. //
  485. // Get the list of shared printers on the server.
  486. // Be aware that share names returned by EnumPrinters
  487. // may be in the form of \\servername\sharename.
  488. //
  489. dwFlags = PRINTER_ENUM_SHARED | (pServerName ? PRINTER_ENUM_NAME : PRINTER_ENUM_LOCAL);
  490. if (! (pPrinterInfo2 = MyEnumPrinters( pServerName, 2, &cPrinters, dwFlags ))) {
  491. cPrinters = 0;
  492. }
  493. for (index = 0; index < cPrinters; index++) {
  494. if (pPrinterInfo2[index].pShareName &&
  495. (pShareName = _tcsrchr(pPrinterInfo2[index].pShareName, TEXT('\\')))) {
  496. pPrinterInfo2[index].pShareName = pShareName + 1;
  497. }
  498. }
  499. //
  500. // Make sure the share name is unique. If not, add a numeric suffix to it.
  501. //
  502. for (shareSuffix = 0; shareSuffix < 1000; shareSuffix++) {
  503. if (shareSuffix > 0) {
  504. *pDest = TEXT('.');
  505. wsprintf( pDest + 1, TEXT("%d"), shareSuffix );
  506. }
  507. //
  508. // Check if the proposed share name matches any of the existing share names.
  509. //
  510. for (index = 0; index < cPrinters; index++) {
  511. if (pPrinterInfo2[index].pShareName &&
  512. _tcsicmp(pPrinterInfo2[index].pShareName, shareName) == 0) {
  513. break;
  514. }
  515. }
  516. //
  517. // Stop searching when we find a unique share name.
  518. //
  519. if (index >= cPrinters) {
  520. break;
  521. }
  522. }
  523. MemFree( pPrinterInfo2 );
  524. return (shareSuffix < 1000) ? StringDup( shareName ) : NULL;
  525. }
  526. BOOL
  527. ShareFaxPrinter(
  528. LPHANDLE hPrinter,
  529. LPTSTR FaxPrinterName
  530. )
  531. {
  532. DWORD i;
  533. DWORD Size;
  534. TCHAR String[4];
  535. HANDLE hPrinterServer;
  536. LPPRINTER_INFO_2 PrinterInfo = NULL;
  537. PRINTER_DEFAULTS PrinterDefaults;
  538. BOOL Rval = FALSE;
  539. LPTSTR ShareName;
  540. ShareName = MakePrinterShareName( NULL, FaxPrinterName );
  541. if (!ShareName) {
  542. return FALSE;
  543. }
  544. if ((!GetPrinter( *hPrinter, 2, NULL, 0, &i )) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
  545. DebugPrint(( TEXT("GetPrinter() failed, ec=%d"), GetLastError() ));
  546. goto exit;
  547. }
  548. PrinterInfo = (LPPRINTER_INFO_2) MemAlloc( i );
  549. if (!PrinterInfo) {
  550. DebugPrint(( TEXT("MemAlloc() failed, size=%d"), i ));
  551. goto exit;
  552. }
  553. if (!GetPrinter( *hPrinter, 2, (LPBYTE) PrinterInfo, i, &i )) {
  554. DebugPrint(( TEXT("GetPrinter() failed, ec=%d"), GetLastError() ));
  555. goto exit;
  556. }
  557. PrinterInfo->pShareName = ShareName;
  558. PrinterInfo->Attributes |= PRINTER_ATTRIBUTE_SHARED;
  559. PrinterInfo->pComment = GetString( IDS_FAX_SHARE_COMMENT );
  560. if (!SetPrinter( *hPrinter, 2, (LPBYTE) PrinterInfo, 0 )) {
  561. DebugPrint(( TEXT("SetPrinter() failed, ec=%d"), GetLastError() ));
  562. goto exit;
  563. }
  564. //
  565. // allow the printer to have remote connections
  566. //
  567. PrinterDefaults.pDatatype = NULL;
  568. PrinterDefaults.pDevMode = NULL;
  569. PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;
  570. if (!OpenPrinter( NULL, &hPrinterServer, &PrinterDefaults )) {
  571. DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() ));
  572. goto exit;
  573. }
  574. //
  575. // remove the fax driver from the list of driver names
  576. //
  577. String[0] = 0;
  578. Size = sizeof(TCHAR);
  579. i = SetPrinterData(
  580. hPrinterServer,
  581. SPLREG_NO_REMOTE_PRINTER_DRIVERS,
  582. REG_SZ,
  583. (LPBYTE) String,
  584. Size
  585. );
  586. if ((i != ERROR_SUCCESS) && (i != ERROR_SUCCESS_RESTART_REQUIRED)) {
  587. DebugPrint(( TEXT("SetPrinterData() failed, ec=%d"), i ));
  588. goto exit;
  589. }
  590. //
  591. // we have to restart the spooler for the
  592. // SetPrinterData() to take affect
  593. //
  594. ClosePrinter( *hPrinter );
  595. PrinterDefaults.pDatatype = NULL;
  596. PrinterDefaults.pDevMode = NULL;
  597. PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS;
  598. if (!OpenPrinter( FaxPrinterName, hPrinter, &PrinterDefaults )) {
  599. DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() ));
  600. goto exit;
  601. }
  602. Rval = TRUE;
  603. exit:
  604. MemFree( PrinterInfo );
  605. MemFree( ShareName );
  606. ClosePrinter( hPrinterServer );
  607. return Rval;
  608. }
  609. BOOL
  610. DeleteFaxPrinters(
  611. HWND hwnd
  612. )
  613. {
  614. PPRINTER_INFO_2 PrinterInfo;
  615. PMONITOR_INFO_2 MonitorInfo;
  616. DWORD Count;
  617. HANDLE hPrinter;
  618. PRINTER_DEFAULTS PrinterDefaults;
  619. DWORD i,j;
  620. LPTSTR FileName = NULL;
  621. PDRIVER_INFO_2 DriverInfo;
  622. PDRIVER_INFO_2 DriverInfoDel;
  623. TCHAR Buffer[MAX_PATH];
  624. PrinterInfo = MyEnumPrinters( NULL, 2, &Count, 0 );
  625. if (!PrinterInfo) {
  626. return FALSE;
  627. }
  628. PrinterDefaults.pDatatype = NULL;
  629. PrinterDefaults.pDevMode = NULL;
  630. PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS;
  631. for (i=0; i<Count; i++) {
  632. //
  633. // is this a fax printer??
  634. //
  635. if (_tcsicmp( PrinterInfo[i].pDriverName, FAX_DRIVER_NAME ) == 0) {
  636. if (PrinterInfo[i].Attributes & PRINTER_ATTRIBUTE_LOCAL) {
  637. if (!OpenPrinter( PrinterInfo[i].pPrinterName, &hPrinter, &PrinterDefaults )) {
  638. DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() ));
  639. continue;
  640. }
  641. {
  642. BOOL DidWeDelete ;
  643. BOOL DidWeClose ;
  644. DWORD LastError ;
  645. DidWeDelete = DeletePrinter( hPrinter ); // Returns 1 even when print jobs are in queue.
  646. if( !DidWeDelete ){
  647. LastError = GetLastError() ;
  648. }
  649. DidWeClose = ClosePrinter( hPrinter );
  650. if( !DidWeClose ){
  651. LastError = GetLastError();
  652. }
  653. }
  654. } else {
  655. DeletePrinterConnection( PrinterInfo[i].pPrinterName );
  656. }
  657. }
  658. }
  659. MemFree( PrinterInfo );
  660. //
  661. // See if any FAX printers are still pending deletion.
  662. //
  663. PrinterInfo = MyEnumPrinters( NULL, 2, &Count, 0 );
  664. if (PrinterInfo) {
  665. for (i=0; i<Count; i++) {
  666. //
  667. // Is this a fax printer? If so, warn the user that it wasn't deleted
  668. //
  669. if (_tcsicmp( PrinterInfo[i].pDriverName, FAX_DRIVER_NAME ) == 0) {
  670. if( PrinterInfo[i].Status == PRINTER_STATUS_PENDING_DELETION ){
  671. PopUpMsgFmt(
  672. hwnd,
  673. IDS_FAX_PRINTER_PENDING_DELETION,
  674. FALSE,
  675. 0,
  676. PrinterInfo[i].pPrinterName
  677. );
  678. }
  679. else {
  680. PopUpMsgFmt(
  681. hwnd,
  682. IDS_COULD_NOT_DELETE_FAX_PRINTER,
  683. FALSE,
  684. 0,
  685. PrinterInfo[i].pPrinterName
  686. );
  687. }
  688. }
  689. }
  690. }
  691. MemFree( PrinterInfo );
  692. MonitorInfo = MyEnumMonitors( &Count );
  693. if (MonitorInfo) {
  694. for (i=0; i<Count; i++) {
  695. if (_tcscmp( MonitorInfo[i].pName, FAX_MONITOR_NAME ) == 0) {
  696. FileName = MonitorInfo[i].pDLLName;
  697. break;
  698. }
  699. }
  700. }
  701. if (!DeleteMonitor( NULL, NULL, FAX_MONITOR_NAME )) {
  702. DebugPrint(( TEXT("DeleteMonitor() failed, ec=%d"), GetLastError() ));
  703. }
  704. if (FileName) {
  705. ExpandEnvironmentStrings( TEXT("%systemroot%\\system32\\"), Buffer, sizeof(Buffer)/sizeof(TCHAR) );
  706. _tcscat( Buffer, FileName );
  707. MyDeleteFile( Buffer );
  708. }
  709. if (MonitorInfo) {
  710. MemFree( MonitorInfo );
  711. }
  712. for (i=0; i<MAX_PLATFORMS; i++) {
  713. DriverInfo = MyEnumDrivers( Platforms[i].PrintPlatform, &Count );
  714. DriverInfoDel = NULL;
  715. if (DriverInfo) {
  716. for (j=0; j<Count; j++) {
  717. if (_tcscmp( DriverInfo[j].pName, FAX_DRIVER_NAME ) == 0) {
  718. DriverInfoDel = &DriverInfo[j];
  719. break;
  720. }
  721. }
  722. }
  723. if (!DeletePrinterDriver( NULL, Platforms[i].PrintPlatform, FAX_DRIVER_NAME )) {
  724. DebugPrint(( TEXT("DeletePrinterDriver() failed, ec=%d"), GetLastError() ));
  725. }
  726. if (DriverInfoDel) {
  727. MyDeleteFile( DriverInfoDel->pDriverPath );
  728. MyDeleteFile( DriverInfoDel->pDataFile );
  729. MyDeleteFile( DriverInfoDel->pConfigFile );
  730. }
  731. if (DriverInfo) {
  732. MemFree( DriverInfo );
  733. }
  734. }
  735. return TRUE;
  736. }
  737. PVOID
  738. MyEnumPrinters(
  739. LPTSTR pServerName,
  740. DWORD level,
  741. PDWORD pcPrinters,
  742. DWORD Flags
  743. )
  744. {
  745. PBYTE pPrinterInfo = NULL;
  746. DWORD cb;
  747. if (!Flags) {
  748. Flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
  749. }
  750. if (!EnumPrinters(Flags, pServerName, level, NULL, 0, &cb, pcPrinters) &&
  751. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  752. (pPrinterInfo = MemAlloc(cb)) &&
  753. EnumPrinters(Flags, pServerName, level, pPrinterInfo, cb, &cb, pcPrinters))
  754. {
  755. return pPrinterInfo;
  756. }
  757. MemFree(pPrinterInfo);
  758. return NULL;
  759. }
  760. PVOID
  761. MyEnumDrivers(
  762. LPTSTR pEnvironment,
  763. PDWORD pcDrivers
  764. )
  765. {
  766. PBYTE pDriverInfo = NULL;
  767. DWORD cb;
  768. if (!EnumPrinterDrivers(NULL, pEnvironment, 2, 0, 0, &cb, pcDrivers ) &&
  769. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  770. (pDriverInfo = MemAlloc(cb)) &&
  771. EnumPrinterDrivers(NULL, pEnvironment, 2, pDriverInfo, cb, &cb, pcDrivers ))
  772. {
  773. return pDriverInfo;
  774. }
  775. MemFree(pDriverInfo);
  776. return NULL;
  777. }
  778. PVOID
  779. MyEnumMonitors(
  780. PDWORD pcMonitors
  781. )
  782. {
  783. PBYTE pMonitorInfo = NULL;
  784. DWORD cb;
  785. if (!EnumMonitors(NULL, 2, 0, 0, &cb, pcMonitors ) &&
  786. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  787. (pMonitorInfo = MemAlloc(cb)) &&
  788. EnumMonitors(NULL, 2, pMonitorInfo, cb, &cb, pcMonitors ))
  789. {
  790. return pMonitorInfo;
  791. }
  792. MemFree(pMonitorInfo);
  793. return NULL;
  794. }