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.

1108 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Abstract:
  4. This module provides functionality for publishing printers
  5. Author:
  6. Steve Wilson (NT) November 1997
  7. Revision History:
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #include "pubprn.hxx"
  12. #include "varconv.hxx"
  13. #include "property.hxx"
  14. #include "dsutil.hxx"
  15. #include "client.h"
  16. #define PPM_FACTOR 48
  17. BOOL
  18. PublishPrinterW(
  19. HWND hwnd,
  20. PCWSTR pszUNCName,
  21. PCWSTR pszDN,
  22. PCWSTR pszCN,
  23. PWSTR *ppszDN,
  24. DWORD dwAction
  25. )
  26. {
  27. PRINTER_DEFAULTS Defaults;
  28. HANDLE hPrinter = NULL;
  29. HANDLE hServer = NULL;
  30. PWSTR pszServerName = NULL;
  31. PWSTR pszPrinterName = NULL;
  32. PPRINTER_INFO_2 pInfo2 = NULL;
  33. DWORD dwRet = ERROR_SUCCESS;
  34. DWORD dwType;
  35. DWORD dwMajorVersion;
  36. DWORD dwDsPresent;
  37. DWORD cbNeeded;
  38. DWORD dwLength;
  39. HRESULT hr;
  40. WCHAR szDNSMachineName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
  41. WCHAR szFullUNCName[MAX_UNC_PRINTER_NAME];
  42. WCHAR szShortServerName[MAX_PATH+1];
  43. PWSTR pszFullUNCName;
  44. PWSTR pszShortServerName;
  45. PWSTR pszFullServerName;
  46. if (InCSRProcess()) {
  47. SetLastError(ERROR_NOT_SUPPORTED);
  48. return FALSE;
  49. }
  50. hr = CoInitialize(NULL);
  51. if (hr != S_OK && hr != S_FALSE) {
  52. SetLastError((DWORD)((HRESULT_FACILITY(hr) == FACILITY_WIN32) ? HRESULT_CODE(hr) : hr));
  53. return FALSE;
  54. }
  55. if (ppszDN)
  56. *ppszDN = NULL;
  57. //
  58. // Get server name
  59. //
  60. if (dwRet = UNC2Server(pszUNCName, &pszServerName))
  61. goto error;
  62. if(!OpenPrinter(pszServerName, &hServer, NULL)) {
  63. dwMajorVersion = 0;
  64. } else {
  65. dwRet = GetPrinterData( hServer,
  66. SPLREG_MAJOR_VERSION,
  67. &dwType,
  68. (PBYTE) &dwMajorVersion,
  69. sizeof dwMajorVersion,
  70. &cbNeeded);
  71. if (dwRet != ERROR_SUCCESS) {
  72. //
  73. // ignore errors and assume lowest version
  74. //
  75. dwMajorVersion = 0;
  76. dwRet = ERROR_SUCCESS;
  77. }
  78. if (dwMajorVersion >= WIN2000_SPOOLER_VERSION) {
  79. hr = MachineIsInMyForest(pszServerName);
  80. if (FAILED(hr)) {
  81. dwRet = HRESULT_CODE(hr);
  82. goto error;
  83. } else if(HRESULT_CODE(hr) == 1) {
  84. //
  85. // Machine is in my forest and is NT5+
  86. //
  87. dwRet = ERROR_INVALID_LEVEL;
  88. goto error;
  89. } else {
  90. //
  91. // Downgrade the version for NT5+ printers published in a non-DS domain
  92. //
  93. dwMajorVersion = WIN2000_SPOOLER_VERSION;
  94. }
  95. }
  96. }
  97. Defaults.pDatatype = NULL;
  98. Defaults.pDevMode = NULL;
  99. Defaults.DesiredAccess = PRINTER_ACCESS_USE;
  100. if (!OpenPrinter((PWSTR) pszUNCName, &hPrinter, &Defaults)) {
  101. dwRet = GetLastError();
  102. goto error;
  103. }
  104. hr = GetPrinterInfo2(hPrinter, &pInfo2);
  105. if (FAILED(hr)) {
  106. dwRet = HRESULT_CODE(hr);
  107. goto error;
  108. }
  109. if (dwRet = UNC2Printer(pInfo2->pPrinterName, &pszPrinterName))
  110. goto error;
  111. if( dwMajorVersion >= WIN2000_SPOOLER_VERSION){
  112. if(dwRet = GetPrinterData( hServer,
  113. SPLREG_DNS_MACHINE_NAME,
  114. &dwType,
  115. (PBYTE) szDNSMachineName,
  116. (INTERNET_MAX_HOST_NAME_LENGTH + 1) * sizeof(WCHAR),
  117. &cbNeeded) != ERROR_SUCCESS ) {
  118. goto error;
  119. }
  120. if (FAILED(hr = StringCchPrintf( szFullUNCName,
  121. COUNTOF(szFullUNCName),
  122. L"\\\\%s\\%s",
  123. szDNSMachineName,
  124. pszPrinterName )))
  125. {
  126. dwRet = HRESULT_CODE(hr);
  127. goto error;
  128. }
  129. dwLength = MAX_PATH + 1;
  130. if (!DnsHostnameToComputerName(pszServerName,
  131. szShortServerName,
  132. &dwLength)) {
  133. dwRet = GetLastError();
  134. goto error;
  135. }
  136. pszFullUNCName = szFullUNCName;
  137. pszFullServerName = szDNSMachineName;
  138. pszShortServerName = szShortServerName+2;
  139. } else {
  140. pszFullUNCName = (PWSTR)pszUNCName;
  141. pszFullServerName = pszServerName+2;
  142. pszShortServerName = pszServerName+2;
  143. }
  144. //
  145. // Verify PrintQueue doesn't already exist
  146. //
  147. if (dwAction != PUBLISHPRINTER_IGNORE_DUPLICATES) {
  148. if(dwRet = PrintQueueExists(hwnd, hPrinter, pszFullUNCName, dwAction, (PWSTR) pszDN, (PWSTR *) ppszDN))
  149. goto error;
  150. }
  151. if (dwRet = PublishDownlevelPrinter(hPrinter,
  152. (PWSTR) pszDN,
  153. (PWSTR) pszCN,
  154. pszFullServerName,
  155. pszShortServerName,
  156. pszFullUNCName,
  157. pszPrinterName,
  158. dwMajorVersion,
  159. ppszDN))
  160. goto error;
  161. error:
  162. if (hPrinter != NULL)
  163. ClosePrinter(hPrinter);
  164. if (hServer != NULL)
  165. ClosePrinter(hServer);
  166. if (pszServerName)
  167. FreeSplMem(pszServerName);
  168. if (pszPrinterName)
  169. FreeSplMem(pszPrinterName);
  170. FreeSplMem(pInfo2);
  171. if (dwRet != ERROR_SUCCESS) {
  172. SetLastError(dwRet);
  173. return FALSE;
  174. }
  175. CoUninitialize();
  176. return TRUE;
  177. }
  178. DWORD
  179. PublishDownlevelPrinter(
  180. HANDLE hPrinter,
  181. PWSTR pszDN,
  182. PWSTR pszCN,
  183. PWSTR pszServerName,
  184. PWSTR pszShortServerName,
  185. PWSTR pszUNCName,
  186. PWSTR pszPrinterName,
  187. DWORD dwVersion,
  188. PWSTR *ppszObjectDN
  189. )
  190. {
  191. HRESULT hr = S_OK;
  192. DWORD dwRet = ERROR_SUCCESS;
  193. IADs *pPrintQueue = NULL;
  194. IADsContainer *pADsContainer = NULL;
  195. IDispatch *pDispatch = NULL;
  196. PWSTR pszCommonName = pszCN;
  197. BSTR bstrADsPath = NULL;
  198. PWSTR pszDNWithDC = NULL;
  199. if (ppszObjectDN)
  200. *ppszObjectDN = NULL;
  201. //
  202. // If pszCN is not supplied, generate default common name
  203. //
  204. if (!pszCommonName || !*pszCommonName) {
  205. dwRet = GetCommonName(hPrinter, &pszCommonName);
  206. if (dwRet != ERROR_SUCCESS) {
  207. hr = dw2hr(dwRet);
  208. BAIL_ON_FAILURE(hr);
  209. }
  210. }
  211. //
  212. // Stick DC in DN
  213. //
  214. if (!(pszDNWithDC = GetDNWithServer(pszDN))) {
  215. pszDNWithDC = pszDN;
  216. }
  217. //
  218. // Get container
  219. //
  220. hr = ADsGetObject(pszDNWithDC, IID_IADsContainer, (void **) &pADsContainer);
  221. BAIL_ON_FAILURE(hr);
  222. //
  223. // Create printqueue
  224. //
  225. hr = pADsContainer->Create(SPLDS_PRINTER_CLASS, pszCommonName, &pDispatch);
  226. BAIL_ON_FAILURE(hr);
  227. hr = pDispatch->QueryInterface(IID_IADs, (void **) &pPrintQueue);
  228. BAIL_ON_FAILURE(hr);
  229. //
  230. // Set properties
  231. //
  232. hr = SetProperties( hPrinter,
  233. pszServerName,
  234. pszShortServerName,
  235. pszUNCName,
  236. pszPrinterName,
  237. dwVersion,
  238. pPrintQueue);
  239. BAIL_ON_FAILURE(hr);
  240. //
  241. // Get ADsPath to printQueue
  242. //
  243. if (ppszObjectDN) {
  244. hr = pPrintQueue->get_ADsPath(&bstrADsPath);
  245. BAIL_ON_FAILURE(hr);
  246. if (!(*ppszObjectDN = AllocGlobalStr(bstrADsPath))) {
  247. dwRet = GetLastError();
  248. hr = dw2hr(dwRet);
  249. BAIL_ON_FAILURE(hr);
  250. }
  251. }
  252. error:
  253. if (pszDNWithDC != pszDN)
  254. FreeSplMem(pszDNWithDC);
  255. if (bstrADsPath)
  256. SysFreeString(bstrADsPath);
  257. if (pszCommonName != pszCN)
  258. FreeSplMem(pszCommonName);
  259. if (pADsContainer)
  260. pADsContainer->Release();
  261. if (pDispatch)
  262. pDispatch->Release();
  263. if (pPrintQueue)
  264. pPrintQueue->Release();
  265. if (FAILED(hr) && ppszObjectDN && *ppszObjectDN)
  266. FreeGlobalStr(*ppszObjectDN);
  267. return hr2dw(hr);
  268. }
  269. HRESULT
  270. SetProperties(
  271. HANDLE hPrinter,
  272. PWSTR pszServerName,
  273. PWSTR pszShortServerName,
  274. PWSTR pszUNCName,
  275. PWSTR pszPrinterName,
  276. DWORD dwVersion,
  277. IADs *pPrintQueue
  278. )
  279. {
  280. HRESULT hr;
  281. hr = SetMandatoryProperties(pszServerName,
  282. pszShortServerName,
  283. pszUNCName,
  284. pszPrinterName,
  285. dwVersion,
  286. pPrintQueue);
  287. BAIL_ON_FAILURE(hr);
  288. SetSpoolerProperties(hPrinter, pPrintQueue, dwVersion);
  289. SetDriverProperties(hPrinter, pPrintQueue);
  290. error:
  291. return hr;
  292. }
  293. HRESULT
  294. SetMandatoryProperties(
  295. PWSTR pszServerName,
  296. PWSTR pszShortServerName,
  297. PWSTR pszUNCName,
  298. PWSTR pszPrinterName,
  299. DWORD dwVersion,
  300. IADs *pPrintQueue
  301. )
  302. {
  303. HRESULT hr;
  304. //
  305. // ServerName
  306. //
  307. hr = put_BSTR_Property(pPrintQueue, SPLDS_SERVER_NAME, pszServerName);
  308. BAIL_ON_FAILURE(hr);
  309. //
  310. // ShortServerName
  311. //
  312. hr = put_BSTR_Property(pPrintQueue, SPLDS_SHORT_SERVER_NAME, pszShortServerName);
  313. BAIL_ON_FAILURE(hr);
  314. //
  315. // UNC Name
  316. //
  317. hr = put_BSTR_Property(pPrintQueue, SPLDS_UNC_NAME, pszUNCName);
  318. BAIL_ON_FAILURE(hr);
  319. //
  320. // PrinterName
  321. //
  322. hr = put_BSTR_Property(pPrintQueue, SPLDS_PRINTER_NAME, pszPrinterName);
  323. BAIL_ON_FAILURE(hr);
  324. //
  325. // versionNumber
  326. //
  327. hr = put_DWORD_Property(pPrintQueue, SPLDS_VERSION_NUMBER, &dwVersion);
  328. BAIL_ON_FAILURE(hr);
  329. hr = pPrintQueue->SetInfo();
  330. if (FAILED(hr))
  331. pPrintQueue->GetInfo();
  332. error:
  333. return hr;
  334. }
  335. HRESULT
  336. SetSpoolerProperties(
  337. HANDLE hPrinter,
  338. IADs *pPrintQueue,
  339. DWORD dwVersion
  340. )
  341. {
  342. HRESULT hr = E_FAIL;
  343. PPRINTER_INFO_2 pInfo2 = NULL;
  344. DWORD cbNeeded;
  345. BYTE Byte;
  346. PWSTR psz;
  347. //
  348. // Get PRINTER_INFO_2 properties
  349. //
  350. if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, 0, &cbNeeded)) {
  351. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  352. hr = dw2hr(GetLastError());
  353. goto error;
  354. }
  355. if (!(pInfo2 = (PPRINTER_INFO_2) AllocSplMem(cbNeeded))) {
  356. hr = dw2hr(GetLastError());
  357. goto error;
  358. }
  359. if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, cbNeeded, &cbNeeded)) {
  360. hr = dw2hr(GetLastError());
  361. goto error;
  362. }
  363. //
  364. // Description
  365. //
  366. hr = PublishDsData( pPrintQueue,
  367. SPLDS_DESCRIPTION,
  368. REG_SZ,
  369. (PBYTE) pInfo2->pComment);
  370. //
  371. // Driver-Name
  372. //
  373. hr = PublishDsData( pPrintQueue,
  374. SPLDS_DRIVER_NAME,
  375. REG_SZ,
  376. (PBYTE) pInfo2->pDriverName);
  377. //
  378. // Location
  379. //
  380. hr = PublishDsData( pPrintQueue,
  381. SPLDS_LOCATION,
  382. REG_SZ,
  383. (PBYTE) pInfo2->pLocation);
  384. //
  385. // portName (Port1,Port2,Port3)
  386. //
  387. if (pInfo2->pPortName) {
  388. PWSTR pszPortName;
  389. //
  390. // copy comma delimited strings to Multi-sz format
  391. //
  392. pszPortName = DelimString2MultiSz(pInfo2->pPortName, L',');
  393. if (pszPortName) {
  394. hr = PublishDsData( pPrintQueue,
  395. SPLDS_PORT_NAME,
  396. REG_MULTI_SZ,
  397. (PBYTE) pszPortName);
  398. FreeSplMem(pszPortName);
  399. }
  400. }
  401. //
  402. // startTime
  403. //
  404. hr = PublishDsData( pPrintQueue,
  405. SPLDS_PRINT_START_TIME,
  406. REG_DWORD,
  407. (PBYTE) &pInfo2->StartTime);
  408. //
  409. // endTime
  410. //
  411. hr = PublishDsData( pPrintQueue,
  412. SPLDS_PRINT_END_TIME,
  413. REG_DWORD,
  414. (PBYTE) &pInfo2->UntilTime);
  415. // keepPrintedJobs
  416. Byte = pInfo2->Attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS ? 1 : 0;
  417. hr = PublishDsData( pPrintQueue,
  418. SPLDS_PRINT_KEEP_PRINTED_JOBS,
  419. REG_BINARY,
  420. (PBYTE) &Byte );
  421. //
  422. // printSeparatorFile
  423. //
  424. hr = PublishDsData( pPrintQueue,
  425. SPLDS_PRINT_SEPARATOR_FILE,
  426. REG_SZ,
  427. (PBYTE) pInfo2->pSepFile);
  428. //
  429. // printShareName
  430. //
  431. hr = PublishDsData( pPrintQueue,
  432. SPLDS_PRINT_SHARE_NAME,
  433. REG_SZ,
  434. (PBYTE) pInfo2->pShareName);
  435. //
  436. // printSpooling
  437. //
  438. if (pInfo2->Attributes & PRINTER_ATTRIBUTE_DIRECT) {
  439. psz = L"PrintDirect";
  440. } else if (pInfo2->Attributes & PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST) {
  441. psz = L"PrintAfterSpooled";
  442. } else {
  443. psz = L"PrintWhileSpooling";
  444. }
  445. hr = PublishDsData( pPrintQueue,
  446. SPLDS_PRINT_SPOOLING,
  447. REG_SZ,
  448. (PBYTE) psz);
  449. //
  450. // priority
  451. //
  452. hr = PublishDsData( pPrintQueue,
  453. SPLDS_PRIORITY,
  454. REG_DWORD,
  455. (PBYTE) &pInfo2->Priority);
  456. //
  457. // Non-Info2 properties
  458. // URL - downlevel machines don't support http printers, so don't publish useless url
  459. //
  460. if (dwVersion >= WIN2000_SPOOLER_VERSION) {
  461. DWORD dwRet, dwType;
  462. PWSTR pszUrl = NULL;
  463. //
  464. // Get the url from the print server
  465. //
  466. dwRet = GetPrinterDataEx( hPrinter,
  467. SPLDS_SPOOLER_KEY,
  468. SPLDS_URL,
  469. &dwType,
  470. (PBYTE) pszUrl,
  471. 0,
  472. &cbNeeded);
  473. if (dwRet == ERROR_MORE_DATA) {
  474. if ((pszUrl = (PWSTR) AllocSplMem(cbNeeded))) {
  475. dwRet = GetPrinterDataEx( hPrinter,
  476. SPLDS_SPOOLER_KEY,
  477. SPLDS_URL,
  478. &dwType,
  479. (PBYTE) pszUrl,
  480. cbNeeded,
  481. &cbNeeded);
  482. if (dwRet == ERROR_SUCCESS && dwType == REG_SZ) {
  483. hr = PublishDsData( pPrintQueue,
  484. SPLDS_URL,
  485. REG_SZ,
  486. (PBYTE) pszUrl);
  487. }
  488. FreeSplMem(pszUrl);
  489. }
  490. }
  491. }
  492. }
  493. error:
  494. FreeSplMem(pInfo2);
  495. return hr;
  496. }
  497. HRESULT
  498. SetDriverProperties(
  499. HANDLE hPrinter,
  500. IADs *pPrintQueue
  501. )
  502. {
  503. DWORD i, cbBytes, dwCount;
  504. LPWSTR pStr;
  505. DWORD dwResult;
  506. LPWSTR pOutput = NULL, pTemp = NULL, pTemp1 = NULL;
  507. DWORD cOutputBytes, cTempBytes;
  508. POINTS point;
  509. WCHAR pBuf[100];
  510. BOOL bInSplSem = TRUE;
  511. DWORD dwTemp, dwPrintRate, dwPrintRateUnit, dwPrintPPM;
  512. HRESULT hr = S_OK;
  513. PPRINTER_INFO_2 pInfo2 = NULL;
  514. PWSTR pszUNCName;
  515. //
  516. // Get UNCName
  517. //
  518. hr = GetPrinterInfo2(hPrinter, &pInfo2);
  519. BAIL_ON_FAILURE(hr);
  520. if (!pInfo2) {
  521. hr = dw2hr(GetLastError());
  522. goto error;
  523. }
  524. pszUNCName = pInfo2->pPrinterName;
  525. //
  526. // DeviceCapability properties
  527. //
  528. pOutput = (PWSTR) AllocSplMem(cOutputBytes = 200);
  529. if (!pOutput) {
  530. hr = dw2hr(GetLastError());
  531. goto error;
  532. }
  533. pTemp = (PWSTR) AllocSplMem(cTempBytes = 200);
  534. if (!pTemp) {
  535. hr = dw2hr(GetLastError());
  536. goto error;
  537. }
  538. //
  539. // printBinNames
  540. //
  541. DevCapMultiSz( pszUNCName,
  542. pPrintQueue,
  543. DC_BINNAMES,
  544. 24,
  545. SPLDS_PRINT_BIN_NAMES);
  546. //
  547. // printCollate (awaiting DC_COLLATE)
  548. //
  549. dwResult = DeviceCapabilities( pszUNCName,
  550. NULL,
  551. DC_COLLATE,
  552. NULL,
  553. NULL);
  554. if (dwResult != GDI_ERROR) {
  555. hr = PublishDsData( pPrintQueue,
  556. SPLDS_PRINT_COLLATE,
  557. REG_BINARY,
  558. (PBYTE) &dwResult);
  559. }
  560. //
  561. // printColor
  562. //
  563. dwResult = DeviceCapabilities( pszUNCName,
  564. NULL,
  565. DC_COLORDEVICE,
  566. NULL,
  567. NULL);
  568. if (dwResult == GDI_ERROR) {
  569. //
  570. // Try alternative method
  571. //
  572. dwResult = ThisIsAColorPrinter(pszUNCName);
  573. }
  574. hr = PublishDsData( pPrintQueue,
  575. SPLDS_PRINT_COLOR,
  576. REG_BINARY,
  577. (PBYTE) &dwResult);
  578. //
  579. // printDuplexSupported
  580. //
  581. dwResult = DeviceCapabilities( pszUNCName,
  582. NULL,
  583. DC_DUPLEX,
  584. NULL,
  585. NULL);
  586. if (dwResult != GDI_ERROR) {
  587. hr = PublishDsData( pPrintQueue,
  588. SPLDS_PRINT_DUPLEX_SUPPORTED,
  589. REG_BINARY,
  590. (PBYTE) &dwResult);
  591. }
  592. //
  593. // printStaplingSupported
  594. //
  595. dwResult = DeviceCapabilities( pszUNCName,
  596. NULL,
  597. DC_STAPLE,
  598. NULL,
  599. NULL);
  600. if (dwResult != GDI_ERROR) {
  601. hr = PublishDsData( pPrintQueue,
  602. SPLDS_PRINT_STAPLING_SUPPORTED,
  603. REG_BINARY,
  604. (PBYTE) &dwResult);
  605. }
  606. //
  607. // printMaxXExtent & printMaxYExtent
  608. //
  609. dwResult = DeviceCapabilities( pszUNCName,
  610. NULL,
  611. DC_MAXEXTENT,
  612. NULL,
  613. NULL);
  614. if (dwResult != GDI_ERROR) {
  615. *((DWORD *) &point) = dwResult;
  616. dwTemp = (DWORD) point.x;
  617. hr = PublishDsData( pPrintQueue,
  618. SPLDS_PRINT_MAX_X_EXTENT,
  619. REG_DWORD,
  620. (PBYTE) &dwTemp);
  621. dwTemp = (DWORD) point.y;
  622. hr = PublishDsData( pPrintQueue,
  623. SPLDS_PRINT_MAX_Y_EXTENT,
  624. REG_DWORD,
  625. (PBYTE) &dwTemp);
  626. }
  627. //
  628. // printMinXExtent & printMinYExtent
  629. //
  630. dwResult = DeviceCapabilities( pszUNCName,
  631. NULL,
  632. DC_MINEXTENT,
  633. NULL,
  634. NULL);
  635. if (dwResult != GDI_ERROR) {
  636. *((DWORD *) &point) = dwResult;
  637. dwTemp = (DWORD) point.x;
  638. hr = PublishDsData( pPrintQueue,
  639. SPLDS_PRINT_MIN_X_EXTENT,
  640. REG_DWORD,
  641. (PBYTE) &dwTemp);
  642. dwTemp = (DWORD) point.y;
  643. hr = PublishDsData( pPrintQueue,
  644. SPLDS_PRINT_MIN_Y_EXTENT,
  645. REG_DWORD,
  646. (PBYTE) &dwTemp);
  647. }
  648. //
  649. // printMediaSupported
  650. //
  651. DevCapMultiSz( pszUNCName,
  652. pPrintQueue,
  653. DC_PAPERNAMES,
  654. 64,
  655. SPLDS_PRINT_MEDIA_SUPPORTED);
  656. //
  657. // printMediaReady
  658. //
  659. DevCapMultiSz( pszUNCName,
  660. pPrintQueue,
  661. DC_MEDIAREADY,
  662. 64,
  663. SPLDS_PRINT_MEDIA_READY);
  664. //
  665. // printNumberUp
  666. //
  667. dwResult = DeviceCapabilities( pszUNCName,
  668. NULL,
  669. DC_NUP,
  670. NULL,
  671. NULL);
  672. if (dwResult != GDI_ERROR) {
  673. //
  674. // DS NUp is boolean
  675. //
  676. dwResult = !!dwResult;
  677. hr = PublishDsData( pPrintQueue,
  678. SPLDS_PRINT_DUPLEX_SUPPORTED,
  679. REG_DWORD,
  680. (PBYTE) &dwResult);
  681. }
  682. //
  683. // printMemory
  684. //
  685. dwResult = DeviceCapabilities( pszUNCName,
  686. NULL,
  687. DC_PRINTERMEM,
  688. NULL,
  689. NULL);
  690. if (dwResult != GDI_ERROR) {
  691. hr = PublishDsData( pPrintQueue,
  692. SPLDS_PRINT_MEMORY,
  693. REG_DWORD,
  694. (PBYTE) &dwResult);
  695. }
  696. //
  697. // printOrientationsSupported
  698. //
  699. dwResult = DeviceCapabilities( pszUNCName,
  700. NULL,
  701. DC_ORIENTATION,
  702. NULL,
  703. NULL);
  704. if (dwResult != GDI_ERROR) {
  705. StringCchCopy(pStr = pBuf, COUNTOF(pBuf), L"PORTRAIT");
  706. if (dwResult == 90 || dwResult == 270) {
  707. ULONG cchBuf = wcslen(pBuf) + 1;
  708. StringCchCopy(pStr = pBuf + cchBuf, COUNTOF(pBuf) - cchBuf, L"LANDSCAPE");
  709. }
  710. else {
  711. pStr = pBuf;
  712. }
  713. pStr += wcslen(pStr) + 1;
  714. *pStr++ = L'\0';
  715. hr = PublishDsData( pPrintQueue,
  716. SPLDS_PRINT_ORIENTATIONS_SUPPORTED,
  717. REG_MULTI_SZ,
  718. (PBYTE) pBuf);
  719. }
  720. //
  721. // printMaxResolutionSupported
  722. //
  723. dwResult = DeviceCapabilities( pszUNCName,
  724. NULL,
  725. DC_ENUMRESOLUTIONS,
  726. NULL,
  727. NULL);
  728. if (dwResult != GDI_ERROR) {
  729. if (cOutputBytes < dwResult*2*sizeof(DWORD)) {
  730. if(!(pTemp1 = (PWSTR) ReallocSplMem(pOutput, 0, cOutputBytes = dwResult*2*sizeof(DWORD))))
  731. goto error;
  732. pOutput = pTemp1;
  733. }
  734. dwResult = DeviceCapabilities( pszUNCName,
  735. NULL,
  736. DC_ENUMRESOLUTIONS,
  737. pOutput,
  738. NULL);
  739. if (dwResult == GDI_ERROR)
  740. goto error;
  741. //
  742. // Find the maximum resolution: we have dwResult*2 resolutions to check
  743. //
  744. for(i = dwTemp = 0 ; i < dwResult*2 ; ++i) {
  745. if (((DWORD *) pOutput)[i] > dwTemp)
  746. dwTemp = ((DWORD *) pOutput)[i];
  747. }
  748. hr = PublishDsData( pPrintQueue,
  749. SPLDS_PRINT_MAX_RESOLUTION_SUPPORTED,
  750. REG_DWORD,
  751. (PBYTE) &dwTemp);
  752. }
  753. //
  754. // printLanguage
  755. //
  756. DevCapMultiSz( pszUNCName,
  757. pPrintQueue,
  758. DC_PERSONALITY,
  759. 32,
  760. SPLDS_PRINT_LANGUAGE);
  761. //
  762. // printRate
  763. // NOTE: If PrintRate is 0, no value is published
  764. //
  765. dwResult = DeviceCapabilities( pszUNCName,
  766. NULL,
  767. DC_PRINTRATE,
  768. NULL,
  769. NULL);
  770. dwPrintRate = dwResult ? dwResult : GDI_ERROR;
  771. if (dwPrintRate != GDI_ERROR) {
  772. hr = PublishDsData( pPrintQueue,
  773. SPLDS_PRINT_RATE,
  774. REG_DWORD,
  775. (PBYTE) &dwPrintRate);
  776. }
  777. //
  778. // printRateUnit
  779. //
  780. dwResult = DeviceCapabilities( pszUNCName,
  781. NULL,
  782. DC_PRINTRATEUNIT,
  783. NULL,
  784. NULL);
  785. dwPrintRateUnit = dwResult;
  786. if (dwPrintRateUnit != GDI_ERROR) {
  787. switch (dwPrintRateUnit) {
  788. case PRINTRATEUNIT_PPM:
  789. pStr = L"PagesPerMinute";
  790. break;
  791. case PRINTRATEUNIT_CPS:
  792. pStr = L"CharactersPerSecond";
  793. break;
  794. case PRINTRATEUNIT_LPM:
  795. pStr = L"LinesPerMinute";
  796. break;
  797. case PRINTRATEUNIT_IPM:
  798. pStr = L"InchesPerMinute";
  799. break;
  800. default:
  801. pStr = L"";
  802. break;
  803. }
  804. hr = PublishDsData( pPrintQueue,
  805. SPLDS_PRINT_RATE_UNIT,
  806. REG_SZ,
  807. (PBYTE) pStr);
  808. }
  809. //
  810. // printPagesPerMinute
  811. // DevCap returns 0 if there is no entry in GPD
  812. //
  813. dwResult = DeviceCapabilities( pszUNCName,
  814. NULL,
  815. DC_PRINTRATEPPM,
  816. NULL,
  817. NULL);
  818. if (dwResult == GDI_ERROR)
  819. dwResult = 0;
  820. dwPrintPPM = dwResult;
  821. //
  822. // If dwPrintPPM == 0, then calculate PPM from PrintRate
  823. //
  824. if (dwPrintPPM == 0) {
  825. if (dwPrintRate == GDI_ERROR) {
  826. dwPrintPPM = GDI_ERROR;
  827. } else {
  828. switch (dwPrintRateUnit) {
  829. case PRINTRATEUNIT_PPM:
  830. dwPrintPPM = dwPrintRate;
  831. break;
  832. case PRINTRATEUNIT_CPS:
  833. case PRINTRATEUNIT_LPM:
  834. dwPrintPPM = dwPrintRate/PPM_FACTOR;
  835. if (dwPrintPPM == 0) {
  836. //
  837. // min PPM is 1
  838. //
  839. dwPrintPPM = 1;
  840. }
  841. break;
  842. default:
  843. dwPrintPPM = GDI_ERROR;
  844. break;
  845. }
  846. }
  847. }
  848. if (dwPrintPPM != GDI_ERROR) {
  849. hr = PublishDsData( pPrintQueue,
  850. SPLDS_PRINT_PAGES_PER_MINUTE,
  851. REG_DWORD,
  852. (PBYTE) &dwPrintPPM);
  853. }
  854. //
  855. // printDriverVersion
  856. //
  857. dwResult = DeviceCapabilities( pszUNCName,
  858. NULL,
  859. DC_VERSION,
  860. NULL,
  861. NULL);
  862. if (dwResult != GDI_ERROR) {
  863. hr = PublishDsData( pPrintQueue,
  864. SPLDS_DRIVER_VERSION,
  865. REG_DWORD,
  866. (PBYTE) &dwResult);
  867. }
  868. error:
  869. FreeSplMem(pInfo2);
  870. if (pOutput)
  871. FreeSplMem(pOutput);
  872. if (pTemp)
  873. FreeSplMem(pTemp);
  874. return hr;
  875. }
  876. HRESULT
  877. PublishDsData(
  878. IADs *pADs,
  879. PWSTR pValue,
  880. DWORD dwType,
  881. PBYTE pData
  882. )
  883. {
  884. HRESULT hr;
  885. BOOL bCreated = FALSE;
  886. switch (dwType) {
  887. case REG_SZ:
  888. hr = put_BSTR_Property(pADs, pValue, (LPWSTR) pData);
  889. break;
  890. case REG_MULTI_SZ:
  891. hr = put_MULTISZ_Property(pADs, pValue, (LPWSTR) pData);
  892. break;
  893. case REG_DWORD:
  894. hr = put_DWORD_Property(pADs, pValue, (DWORD *) pData);
  895. break;
  896. case REG_BINARY:
  897. hr = put_BOOL_Property(pADs, pValue, (BOOL *) pData);
  898. break;
  899. default:
  900. hr = dw2hr(ERROR_INVALID_PARAMETER);
  901. }
  902. BAIL_ON_FAILURE(hr);
  903. hr = pADs->SetInfo();
  904. if (FAILED(hr))
  905. pADs->GetInfo();
  906. error:
  907. return hr;
  908. }