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.

1834 lines
49 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. --*/
  4. // NTRAID#NTBUG9-553877-2002/02/28-yasuho-: Security: mandatory changes
  5. // NTRAID#NTBUG9-576656-2002/03/14-yasuho-: Possible buffer overrun
  6. // NTRAID#NTBUG9-576658-2002/03/14-yasuho-: Possible divide by zero
  7. // NTRAID#NTBUG9-576660-2002/03/14-yasuho-: Need impersonate for file access
  8. // NTRAID#NTBUG9-576661-2002/03/14-yasuho-: Remove the dead codes
  9. #include "pdev.h"
  10. #include "alpsres.h"
  11. #include "dither.h"
  12. #include <stdio.h>
  13. // #include <winsplp.h>
  14. INT iCompTIFF( BYTE *, int, BYTE *, int );
  15. HANDLE RevertToPrinterSelf( VOID );
  16. BOOL ImpersonatePrinterClient( HANDLE );
  17. BOOL bTextQuality(
  18. PDEVOBJ pdevobj);
  19. BOOL IsAsfOkMedia(
  20. PDEVOBJ pdevobj);
  21. BOOL
  22. bDataSpool(
  23. PDEVOBJ pdevobj,
  24. HANDLE hFile,
  25. LPSTR pBuf,
  26. DWORD dwLen);
  27. BOOL
  28. bSpoolOut(
  29. PDEVOBJ pdevobj);
  30. #define DATASPOOL(p, f, s, n) \
  31. if (TRUE != bDataSpool((p), (f), (s), (n))) \
  32. return FALSE;
  33. #define SPOOLOUT(p) \
  34. if (TRUE != bSpoolOut(p)) \
  35. return FALSE;
  36. //
  37. // Decision table for media type/paper
  38. // source selection. To avoid hardware damage,
  39. // we will select "manual feed" whenever ASF is
  40. // not appropriate to specified media.
  41. //
  42. static struct {
  43. BOOL bAsfOk; // Can print on ASF
  44. // Add new attributes here
  45. } gMediaType[MAX_MEDIATYPES] = {
  46. {1}, // PPC (Normal)
  47. {1}, // PPC (Fine)
  48. {1}, // OHP (Normal)
  49. {1}, // OHP (Fine)
  50. {1}, // ExcOHP (Normal)
  51. {1}, // ExcOHP (Fine)
  52. {0}, // Iron (PPC)
  53. {0}, // Iron (OHP)
  54. {0}, // Thick Paper
  55. {1}, // Postcard
  56. {1}, // High Grade Paper
  57. {0}, // Back Print Film
  58. {0}, // Labeca Sheet
  59. {0}, // CD Master
  60. {1}, // Dye-sub Paper
  61. {1}, // Dye-sub Label
  62. {0}, // Glossy Paper
  63. {1}, // VD Photo Film
  64. {1}, // VD Photo Postcard
  65. // Add new media type here
  66. };
  67. static
  68. PAPERSIZE
  69. gPaperSize[] = {
  70. {2, 4800 * 2, 5960 * 2, 0, 0, 0, 1}, // Letter
  71. {3, 4800 * 2, 7755 * 2, 0, 0, 0, 1}, // Legal
  72. {1, 4190 * 2, 5663 * 2, 0, 0, 0, 1}, // Exective
  73. {4, 4800 * 2, 6372 * 2, 0, 0, 0, 1}, // A4
  74. {5, 4138 * 2, 5430 * 2, 0, 0, 0, 1}, // B5
  75. {6, 2202 * 2, 2856 * 2, 0, 0, 0, 1}, // Postcard
  76. {6, 4564 * 2, 2856 * 2, 0, 0, 0, 1}, // Double Postcard
  77. {7, 2202 * 2, 3114 * 2, 0, 0, 0, 1}, // Photo Color Label
  78. {7, 2202 * 2, 2740 * 2, 0, 0, 0, 1}, // Glossy Label
  79. {0, 2030 * 2, 3164 * 2, 0, 0, 0, 1}, // CD Master
  80. {6, 2202 * 2, 3365 * 2, 0, 0, 0, 1}, // VD Photo Postcard
  81. /* Add new paper sizes here */
  82. };
  83. #define PAPER_SIZE_LETTER 0
  84. #define PAPER_SIZE_LEGAL 1
  85. #define PAPER_SIZE_EXECTIVE 2
  86. #define PAPER_SIZE_A4 3
  87. #define PAPER_SIZE_B5 4
  88. #define PAPER_SIZE_POSTCARD 5
  89. #define PAPER_SIZE_DOUBLE_POSTCARD 6
  90. #define PAPER_PHOTO_COLOR_LABEL 7
  91. #define PAPER_GLOSSY_LABEL 8
  92. #define PAPER_CD_MASTER 9
  93. #define PAPER_VD_PHOTO_POSTCARD 10
  94. /* Add new paper sizes here */
  95. #define MAX_PAPERS (sizeof(gPaperSize)/sizeof(gPaperSize[0]))
  96. //
  97. // ---- F U N C T I O N S ----
  98. //
  99. //////////////////////////////////////////////////////////////////////////
  100. // Function: OEMEnablePDEV
  101. //
  102. // Description: OEM callback for DrvEnablePDEV;
  103. // allocate OEM specific memory block
  104. //
  105. // Parameters:
  106. //
  107. // pdevobj Pointer to the DEVOBJ. pdevobj->pdevOEM is undefined.
  108. // pPrinterName name of the current printer.
  109. // cPatterns, phsurfPatterns, cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo:
  110. // These parameters are identical to what's passed
  111. // into DrvEnablePDEV.
  112. // pded points to a function table which contains the
  113. // system driver's implementation of DDI entrypoints.
  114. //
  115. // Returns:
  116. // Pointer to the PDEVOEM
  117. //
  118. // Comments:
  119. //
  120. //
  121. // History:
  122. //
  123. //////////////////////////////////////////////////////////////////////////
  124. PDEVOEM APIENTRY
  125. OEMEnablePDEV(
  126. PDEVOBJ pdevobj,
  127. PWSTR pPrinterName,
  128. ULONG cPatterns,
  129. HSURF *phsurfPatterns,
  130. ULONG cjGdiInfo,
  131. GDIINFO* pGdiInfo,
  132. ULONG cjDevInfo,
  133. DEVINFO* pDevInfo,
  134. DRVENABLEDATA *pded)
  135. {
  136. PCURRENTSTATUS pTemp = NULL;
  137. VERBOSE((DLLTEXT("OEMEnablePDEV() entry.\n")));
  138. pdevobj->pdevOEM = NULL;
  139. // Allocate minidriver private PDEV block.
  140. pTemp = (PCURRENTSTATUS)MemAllocZ(sizeof(CURRENTSTATUS));
  141. if (NULL == pTemp) {
  142. ERR(("Memory allocation failure.\n"));
  143. goto FAIL_NO_MEMORY;
  144. }
  145. #define MAX_RASTER_PIXELS 5100
  146. // In worstcase, Photo color printing mode use 4 bits par pixel
  147. #define MAX_RASTER_BYTES (MAX_RASTER_PIXELS + 1 / 2)
  148. // Buffers for four plane rasters and one for the
  149. // the scratch work enough for worstcase compression
  150. // overhead.
  151. // The 1st one byte is used for On/Off flag.
  152. #define MAX_RASTER_BUFFER_BYTES \
  153. (4 + MAX_RASTER_BYTES * 5 + (MAX_RASTER_BYTES >> 4))
  154. pTemp->pData = (PBYTE)MemAllocZ(MAX_RASTER_BUFFER_BYTES);
  155. if (NULL == pTemp->pData) {
  156. ERR(("Memory allocation failure.\n"));
  157. goto FAIL_NO_MEMORY;
  158. }
  159. pTemp->pRaster[0] = pTemp->pData;
  160. pTemp->pRaster[1] = pTemp->pRaster[0] + (1 + MAX_RASTER_BYTES);
  161. pTemp->pRaster[2] = pTemp->pRaster[1] + (1 + MAX_RASTER_BYTES);
  162. pTemp->pRaster[3] = pTemp->pRaster[2] + (1 + MAX_RASTER_BYTES);
  163. pTemp->pData2 = pTemp->pRaster[3] + (1 + MAX_RASTER_BYTES);
  164. pTemp->pPaperSize = (PAPERSIZE *)MemAllocZ(
  165. sizeof (gPaperSize));
  166. if (NULL == pTemp->pPaperSize) {
  167. ERR(("Memory allocation failure.\n"));
  168. goto FAIL_NO_MEMORY;
  169. }
  170. CopyMemory(pTemp->pPaperSize, gPaperSize,
  171. sizeof (gPaperSize));
  172. // Set minidriver PDEV address.
  173. pdevobj->pdevOEM = (MINIDEV *)MemAllocZ(sizeof(MINIDEV));
  174. if (NULL == pdevobj->pdevOEM) {
  175. ERR(("Memory allocation failure.\n"));
  176. goto FAIL_NO_MEMORY;
  177. }
  178. MINIDEV_DATA(pdevobj) = pTemp;
  179. return pdevobj->pdevOEM;
  180. FAIL_NO_MEMORY:
  181. if (NULL != pTemp) {
  182. if (NULL != pTemp->pData) {
  183. MemFree(pTemp->pData);
  184. }
  185. if (NULL != pTemp->pPaperSize) {
  186. MemFree(pTemp->pPaperSize);
  187. }
  188. MemFree(pTemp);
  189. }
  190. return NULL;
  191. }
  192. //////////////////////////////////////////////////////////////////////////
  193. // Function: OEMDisablePDEV
  194. //
  195. // Description: OEM callback for DrvDisablePDEV;
  196. // free all allocated OEM specific memory block(s)
  197. //
  198. // Parameters:
  199. //
  200. // pdevobj Pointer to the DEVOBJ.
  201. //
  202. // Returns:
  203. // None
  204. //
  205. // Comments:
  206. //
  207. //
  208. // History:
  209. //
  210. //////////////////////////////////////////////////////////////////////////
  211. VOID APIENTRY
  212. OEMDisablePDEV(
  213. PDEVOBJ pdevobj)
  214. {
  215. PCURRENTSTATUS pTemp;
  216. VERBOSE((DLLTEXT("OEMDisablePDEV() entry.\n")));
  217. if ( NULL != pdevobj->pdevOEM ) {
  218. pTemp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  219. if (NULL != pTemp) {
  220. if (NULL != pTemp->pData) {
  221. MemFree(pTemp->pData);
  222. }
  223. if (NULL != pTemp->pPaperSize) {
  224. MemFree(pTemp->pPaperSize);
  225. }
  226. MemFree( pTemp );
  227. }
  228. MemFree( pdevobj->pdevOEM );
  229. pdevobj->pdevOEM = NULL;
  230. }
  231. }
  232. BOOL APIENTRY
  233. OEMResetPDEV(
  234. PDEVOBJ pdevobjOld,
  235. PDEVOBJ pdevobjNew )
  236. {
  237. PCURRENTSTATUS pTempOld, pTempNew;
  238. PBYTE pTemp;
  239. VERBOSE((DLLTEXT("OEMResetPDEV entry.\n")));
  240. // Do some verificatin on PDEV data passed in.
  241. pTempOld = (PCURRENTSTATUS)MINIDEV_DATA(pdevobjOld);
  242. pTempNew = (PCURRENTSTATUS)MINIDEV_DATA(pdevobjNew);
  243. // Copy mindiriver specific part of PDEV
  244. if (NULL != pTempNew && NULL != pTempOld) {
  245. // NTRAID#NTBUG9-279876-2002/03/14-yasuho-: Should implement OEMResetPDEV().
  246. // NTRAID#NTBUG9-249133-2002/03/14-yasuho-: 2nd page is distorted with duplex.
  247. // This printer doesn't have duplex but we should copy them.
  248. pTempNew->iCurrentResolution = pTempOld->iCurrentResolution;
  249. pTempNew->iPaperQuality = pTempOld->iPaperQuality;
  250. pTempNew->iPaperSize = pTempOld->iPaperSize;
  251. pTempNew->iPaperSource = pTempOld->iPaperSource;
  252. pTempNew->iTextQuality = pTempOld->iTextQuality;
  253. pTempNew->iModel = pTempOld->iModel;
  254. pTempNew->iDither = pTempOld->iDither;
  255. pTempNew->fRequestColor = pTempOld->fRequestColor;
  256. pTempNew->iUnitScale = pTempOld->iUnitScale;
  257. pTempNew->iEmulState = pTempOld->iEmulState;
  258. pTempNew->bXflip = pTempOld->bXflip;
  259. }
  260. return TRUE;
  261. }
  262. VOID
  263. XFlip(
  264. PDEVOBJ pdevobjOld,
  265. PCURRENTSTATUS pdevOEM,
  266. PBYTE pBuf,
  267. DWORD dwLen)
  268. {
  269. INT i, j, k;
  270. BYTE jTemp, jTemp2;
  271. #define SWAP_3BYTES(p, q) { \
  272. jTemp = *(PBYTE)(p); \
  273. *(PBYTE)(p) = *(PBYTE)(q); \
  274. *(PBYTE)(q) = jTemp; \
  275. jTemp = *((PBYTE)(p) + 1); \
  276. *((PBYTE)(p) + 1) = *((PBYTE)(q) + 1); \
  277. *((PBYTE)(q) + 1) = jTemp; \
  278. jTemp = *((PBYTE)(p) + 2); \
  279. *((PBYTE)(p) + 2) = *((PBYTE)(q) + 2); \
  280. *((PBYTE)(q) + 2) = jTemp; }
  281. if (pdevOEM->fRequestColor) {
  282. j = (dwLen / 3) * 3 - 3;
  283. for (i = 0; i < j; i += 3, j -= 3) {
  284. SWAP_3BYTES(pBuf + i, pBuf + j);
  285. }
  286. }
  287. else {
  288. j = dwLen - 1;
  289. for (i = 0; i < j; i++, j--) {
  290. jTemp = pBuf[j];
  291. jTemp2 = 0;
  292. for (k = 0; k < 8; k++) {
  293. if ((jTemp >> k) & 1) {
  294. jTemp2 |= (1 << (7 - k));
  295. }
  296. }
  297. if (i == j) {
  298. pBuf[j] = jTemp2;
  299. continue;
  300. }
  301. jTemp = pBuf[i];
  302. pBuf[i] = jTemp2;
  303. jTemp2 = 0;
  304. for (k = 0; k < 8; k++) {
  305. if ((jTemp >> k) & 1) {
  306. jTemp2 |= (1 << (7 - k));
  307. }
  308. }
  309. pBuf[j] = jTemp2;
  310. }
  311. }
  312. }
  313. BOOL APIENTRY
  314. OEMFilterGraphics(
  315. PDEVOBJ pdevobj,
  316. PBYTE pBuf,
  317. DWORD dwLen)
  318. {
  319. PCURRENTSTATUS lpnp;
  320. int i, x;
  321. WORD wByteLen, wDataSize;
  322. BYTE bRed, bGreen, bBlue;
  323. BYTE py, pm, pc, pk, rm;
  324. BYTE by, bm, bc, bk;
  325. BYTE bCmd[128];
  326. LONG iTemp;
  327. INT iColor, iPlane;
  328. BYTE *pTemp;
  329. BOOL bLast = FALSE;
  330. WORD wTemp;
  331. PBYTE pCmd;
  332. lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  333. VERBOSE(("%d lines left in logical page.\n",
  334. lpnp->wRasterCount));
  335. // We clip off any raster lines exceeding the
  336. // harware margins since it will feed paper too
  337. // much and we cannot back feed the paper
  338. // for 2nd plane and aftter. This result as
  339. // "only cyan (1st plane) image is printed on
  340. // paper."
  341. if (lpnp->wRasterCount <= 0) {
  342. WARNING(("Line beyond page length.\n"));
  343. // We discard this line silently.
  344. return TRUE;
  345. }
  346. else if (lpnp->wRasterCount <= 1) {
  347. // The last raster in logical page,
  348. // Need special handling.
  349. bLast = TRUE;
  350. }
  351. lpnp->wRasterCount--;
  352. // Do x-flip when requested.
  353. if (lpnp->bXflip) {
  354. XFlip(pdevobj, MINIDEV_DATA(pdevobj), pBuf, dwLen);
  355. }
  356. // Get resulting buffer length in bytes.
  357. if ( lpnp->fRequestColor ) {
  358. if ((dwLen / 3) > MAX_RASTER_BYTES) {
  359. ERR((DLLTEXT("dwLen is too big (%d).\n"), dwLen));
  360. return FALSE;
  361. }
  362. // NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
  363. // The pointer(s) will be not valid if the MDP_StartPage() has been failed.
  364. if (!lpnp->pRaster)
  365. return FALSE;
  366. wByteLen = (WORD)(dwLen / 3);
  367. memset(lpnp->pRaster[0], 0, wByteLen+1);
  368. memset(lpnp->pRaster[1], 0, wByteLen+1);
  369. memset(lpnp->pRaster[2], 0, wByteLen+1);
  370. memset(lpnp->pRaster[3], 0, wByteLen+1);
  371. }
  372. else {
  373. if (dwLen > MAX_RASTER_BYTES) {
  374. ERR((DLLTEXT("dwLen is too big (%d).\n"), dwLen));
  375. return FALSE;
  376. }
  377. wByteLen = (WORD)dwLen;
  378. }
  379. // Check if we have K ribbon
  380. if (NULL != lpnp->pRasterK) {
  381. // NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
  382. // The pointer(s) will be not valid if the MDP_StartPage() has been failed.
  383. if (!lpnp->pRasterK)
  384. return FALSE;
  385. lpnp->pRasterK[0] = 0;
  386. }
  387. if ( lpnp->fRequestColor ) {
  388. // NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
  389. // The pointer(s) will be not valid if the MDP_StartPage() has been failed.
  390. if (!lpnp->pRasterC || !lpnp->pRasterM || !lpnp->pRasterY)
  391. return FALSE;
  392. lpnp->pRasterC[0] = 0;
  393. lpnp->pRasterM[0] = 0;
  394. lpnp->pRasterY[0] = 0;
  395. for ( i = 0, x = 0; i+2 < (INT)dwLen ; i+=3, x++ ) {
  396. bRed = pBuf[i];
  397. bGreen = pBuf[i+1];
  398. bBlue = pBuf[i+2];
  399. // RGB -> YMCK
  400. // DITHER_OHP: No longer used.
  401. switch ( lpnp->iTextQuality ) {
  402. case CMDID_TEXTQUALITY_PHOTO:
  403. bPhotoConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
  404. // Processing dither
  405. bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
  406. break;
  407. case CMDID_TEXTQUALITY_GRAPHIC:
  408. bBusinessConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
  409. // Processing dither
  410. bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
  411. break;
  412. case CMDID_TEXTQUALITY_CHARACTER:
  413. bCharacterConvert(pdevobj, bRed, bGreen, bBlue, &py, &pm, &pc, &pk);
  414. // Processing dither
  415. bDitherProcess(pdevobj, x, py, pm, pc, pk, &by, &bm, &bc, &bk);
  416. break;
  417. //case CMDID_TEXTQUALITY_GRAY: dead code
  418. }
  419. if ((lpnp->iDither == DITHER_DYE) || (lpnp->iDither == DITHER_VD)) {
  420. if ( bc ) {
  421. lpnp->pRasterC[0] = 1;
  422. lpnp->pRasterC[1 + x / 2] |= (BYTE)(bc << ((x % 2) ? 0 : 4));
  423. }
  424. if ( bm ) {
  425. lpnp->pRasterM[0] = 1;
  426. lpnp->pRasterM[1 + x / 2] |= (BYTE)(bm << ((x % 2) ? 0 : 4));
  427. }
  428. if ( by ) {
  429. lpnp->pRasterY[0] = 1;
  430. lpnp->pRasterY[1 + x / 2] |= (BYTE)(by << ((x % 2) ? 0 : 4));
  431. }
  432. // K make sure we have K ribbon
  433. if ( bk && (lpnp->iDither == DITHER_VD) ) {
  434. lpnp->pRasterK[0] = 1;
  435. lpnp->pRasterK[1 + x / 2] |= (BYTE)(bk << ((x % 2) ? 0 : 4));
  436. }
  437. } else {
  438. if ( bc ) {
  439. lpnp->pRasterC[0] = 1;
  440. lpnp->pRasterC[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
  441. }
  442. if ( bm ) {
  443. lpnp->pRasterM[0] = 1;
  444. lpnp->pRasterM[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
  445. }
  446. if ( by ) {
  447. lpnp->pRasterY[0] = 1;
  448. lpnp->pRasterY[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
  449. }
  450. // K make sure we have K ribbon
  451. if ( bk && lpnp->pRasterK ) {
  452. lpnp->pRasterK[0] = 1;
  453. lpnp->pRasterK[1 + x / 8] |= (BYTE)(0x80 >> (x % 8));
  454. }
  455. }
  456. }
  457. }
  458. else {
  459. // Monochrome.
  460. pTemp = pBuf;
  461. for (i = 0; i < wByteLen; i++, pTemp++) {
  462. if (*pTemp) {
  463. lpnp->pRasterK[0] = 1;
  464. break;
  465. }
  466. }
  467. }
  468. // Loop process for each color start here.
  469. for ( iPlane = 0; iPlane < 4; iPlane++ ) {
  470. if (NONE == lpnp->PlaneColor[iPlane]) {
  471. // No more plane to process.
  472. break;
  473. }
  474. if (!lpnp->fRequestColor) {
  475. pTemp = pBuf;
  476. }
  477. else {
  478. // Color rasters
  479. pTemp = lpnp->pRaster[iPlane] + 1;
  480. }
  481. // If we do not have ink on this raster line,
  482. // skip this line, just move cursor to the next one.
  483. if (0 == lpnp->pRaster[iPlane][0]) {
  484. lpnp->wRasterOffset[iPlane]++;
  485. continue;
  486. }
  487. // We have ink, output data.
  488. iColor = lpnp->PlaneColor[iPlane];
  489. if (0 > iColor) {
  490. iColor *= -1;
  491. lpnp->PlaneColor[iPlane] = iColor;
  492. // Ink selection commands
  493. switch (iColor) {
  494. case CYAN:
  495. DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
  496. "\x1B\x1A\x01\x00\x72", 5);
  497. break;
  498. case MAGENTA:
  499. DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
  500. "\x1B\x1A\x02\x00\x72", 5);
  501. break;
  502. case YELLOW:
  503. DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
  504. "\x1B\x1A\x03\x00\x72", 5);
  505. break;
  506. case BLACK:
  507. DATASPOOL(pdevobj, lpnp->TempFile[iPlane],
  508. "\x1B\x1A\x00\x01\x72", 5);
  509. break;
  510. default:
  511. ERR((DLLTEXT("Invalid color or plane IDs (%d, %d).\n"),
  512. lpnp->PlaneColor[iPlane], iPlane));
  513. return FALSE;
  514. }
  515. }
  516. // First we move cursor to the correct raster offset.
  517. if (0 < lpnp->wRasterOffset[iPlane]) {
  518. // Send Y cursor move command
  519. if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
  520. "\x1B\x2A\x62%c%c\x59",
  521. LOBYTE(lpnp->wRasterOffset[iPlane]),
  522. HIBYTE(lpnp->wRasterOffset[iPlane]))))
  523. return FALSE;
  524. DATASPOOL(pdevobj, lpnp->TempFile[iPlane], bCmd, (DWORD)(pCmd - bCmd));
  525. // Reset Y position index.
  526. lpnp->wRasterOffset[iPlane] = 0;
  527. }
  528. // Decide if we want to do compress
  529. if ((lpnp->iDither == DITHER_DYE) || (lpnp->iDither == DITHER_VD))
  530. wDataSize = ( wByteLen + 1 ) / 2; // 2 pixels par byte
  531. else
  532. wDataSize = ( wByteLen + 7 ) / 8; // 8 pixels par byte
  533. if ((lpnp->iDither != DITHER_DYE) && (lpnp->iDither != DITHER_VD)) {
  534. // NTRAID#NTBUG9-24281-2002/03/14-yasuho-:
  535. // large bitmap does not printed on 1200dpi.
  536. // Unnecessary data were sent to printer.
  537. wTemp = bPlaneSendOrderCMY(lpnp) ? wDataSize : wByteLen;
  538. if ((iTemp = iCompTIFF(lpnp->pData2,
  539. MAX_RASTER_BUFFER_BYTES - (1 + MAX_RASTER_BYTES)*4,
  540. pTemp, wTemp)) > 0 && iTemp < wTemp) {
  541. pTemp = lpnp->pData2;
  542. wDataSize = (WORD)iTemp;
  543. // Turn on compression mode.
  544. if (lpnp->iCompMode[iPlane] != COMP_TIFF4) {
  545. DATASPOOL(pdevobj, lpnp->TempFile[iPlane], "\x1B*b\x02\x00M", 6);
  546. lpnp->iCompMode[iPlane] = COMP_TIFF4;
  547. }
  548. }
  549. else if (lpnp->iCompMode[iPlane] != COMP_NONE) {
  550. // Turn off compression mode.
  551. DATASPOOL(pdevobj, lpnp->TempFile[iPlane], "\x1B*b\x00\x00M", 6);
  552. lpnp->iCompMode[iPlane] = COMP_NONE;
  553. }
  554. } // not DITHER_DYE
  555. //
  556. // a) ESC * xx V - one raster output, mo move.
  557. // b) ESC * xx W - one raster output, move to next raster.
  558. //
  559. // Use a) on the last raster to avoid page eject. For the
  560. // other rasters use b).
  561. // Send one raster data
  562. if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
  563. "\x1B\x2A\x62%c%c%c",
  564. LOBYTE(wDataSize), HIBYTE(wDataSize),
  565. (BYTE)(bLast ? 0x56 : 0x57))))
  566. return FALSE;
  567. DATASPOOL(pdevobj, lpnp->TempFile[iPlane], bCmd, (DWORD)(pCmd - bCmd));
  568. DATASPOOL(pdevobj, lpnp->TempFile[iPlane], pTemp, wDataSize);
  569. } // end of Color loop
  570. lpnp->y++;
  571. return TRUE;
  572. }
  573. INT
  574. GetPlaneColor(
  575. PDEVOBJ pdevobj,
  576. PCURRENTSTATUS lpnp,
  577. INT iPlane)
  578. {
  579. INT iColor;
  580. iColor = NONE;
  581. if (!lpnp->fRequestColor) {
  582. if (0 == iPlane) {
  583. iColor = BLACK;
  584. }
  585. return iColor;
  586. }
  587. // Color
  588. // NTRAID#NTBUG9-24281-2002/03/14-yasuho-:
  589. // large bitmap does not printed on 1200dpi.
  590. // Do not use black plane (K) on the 1200dpi with color mode.
  591. if (bPlaneSendOrderCMY(lpnp)) {
  592. switch (iPlane) {
  593. case 0:
  594. iColor = CYAN;
  595. break;
  596. case 1:
  597. iColor = MAGENTA;
  598. break;
  599. case 2:
  600. iColor = YELLOW;
  601. break;
  602. }
  603. }
  604. else if (bPlaneSendOrderMCY(lpnp)) {
  605. switch (iPlane) {
  606. case 0:
  607. iColor = MAGENTA;
  608. break;
  609. case 1:
  610. iColor = CYAN;
  611. break;
  612. case 2:
  613. iColor = YELLOW;
  614. break;
  615. }
  616. }
  617. else if (bPlaneSendOrderYMC(lpnp)) {
  618. switch (iPlane) {
  619. case 0:
  620. iColor = YELLOW;
  621. break;
  622. case 1:
  623. iColor = MAGENTA;
  624. break;
  625. case 2:
  626. iColor = CYAN;
  627. break;
  628. }
  629. }
  630. else if (bPlaneSendOrderCMYK(lpnp)) {
  631. switch (iPlane) {
  632. case 0:
  633. iColor = CYAN;
  634. break;
  635. case 1:
  636. iColor = MAGENTA;
  637. break;
  638. case 2:
  639. iColor = YELLOW;
  640. break;
  641. case 3:
  642. iColor = BLACK;
  643. break;
  644. }
  645. }
  646. return iColor;
  647. }
  648. VOID
  649. MDP_StartDoc(
  650. PDEVOBJ pdevobj,
  651. PCURRENTSTATUS pdevOEM)
  652. {
  653. VERBOSE(("MDP_StartDoc called.\n"));
  654. WRITESPOOLBUF(pdevobj, "\x1B\x65\x1B\x25\x80\x41", 6);
  655. }
  656. VOID
  657. MDP_EndDoc(
  658. PDEVOBJ pdevobj,
  659. PCURRENTSTATUS pdevOEM)
  660. {
  661. WRITESPOOLBUF(pdevobj, "\x1B\x25\x00\x58", 4);
  662. }
  663. BOOL
  664. MDP_CreateTempFile(
  665. PDEVOBJ pdevobj,
  666. PCURRENTSTATUS pdevOEM,
  667. INT iPlane)
  668. {
  669. HANDLE hFile;
  670. BOOL bRet = FALSE;
  671. HANDLE hToken = NULL;
  672. PBYTE pBuf = NULL;
  673. DWORD dwSize, dwNeeded = 0;
  674. pdevOEM->TempName[iPlane][0] = __TEXT('\0');
  675. pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
  676. dwSize = (MAX_PATH + 1) * sizeof(WCHAR);
  677. for (;;) {
  678. if ((pBuf = MemAlloc(dwSize)) == NULL)
  679. goto out;
  680. if (GetPrinterData(pdevobj->hPrinter, SPLREG_DEFAULT_SPOOL_DIRECTORY,
  681. NULL, pBuf, dwSize, &dwNeeded) == ERROR_SUCCESS)
  682. break;
  683. if (dwNeeded < dwSize || GetLastError() != ERROR_MORE_DATA)
  684. goto out;
  685. MemFree(pBuf);
  686. dwSize = dwNeeded;
  687. }
  688. if (!(hToken = RevertToPrinterSelf()))
  689. goto out;
  690. if (!GetTempFileName((LPWSTR)pBuf, TEMP_NAME_PREFIX, 0,
  691. pdevOEM->TempName[iPlane])) {
  692. ERR((DLLTEXT("GetTempFileName failed (%d).\n"), GetLastError()))
  693. goto out;
  694. }
  695. hFile = CreateFile(pdevOEM->TempName[iPlane],
  696. (GENERIC_READ | GENERIC_WRITE), 0, NULL,
  697. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  698. if (hFile == INVALID_HANDLE_VALUE) {
  699. ERR((DLLTEXT("CreateFile failed.\n")))
  700. DeleteFile(pdevOEM->TempName[iPlane]);
  701. goto out;
  702. }
  703. pdevOEM->TempFile[iPlane] = hFile;
  704. bRet = TRUE;
  705. out:
  706. if (pBuf) MemFree(pBuf);
  707. if (hToken) (void)ImpersonatePrinterClient(hToken);
  708. return bRet;
  709. }
  710. BOOL
  711. MDP_StartPage(
  712. PDEVOBJ pdevobj,
  713. PCURRENTSTATUS pdevOEM)
  714. {
  715. LONG iPageLength;
  716. INT iPaperSizeID;
  717. BYTE bCmd[128];
  718. INT iColor, iPlane;
  719. PBYTE pCmd;
  720. // Set resolution
  721. switch (pdevOEM->iCurrentResolution) {
  722. case DPI1200:
  723. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x04\x52", 5);
  724. break;
  725. case DPI600:
  726. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x03\x52", 5);
  727. break;
  728. case DPI300:
  729. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x74\x02\x52", 5);
  730. break;
  731. }
  732. // Set Paper Dimentions
  733. // Make sure top margin is 0 and we are at top.
  734. WRITESPOOLBUF(pdevobj, "\x1B\x26\x6C\x00\x00\x45", 6);
  735. WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x00\x0C", 5);
  736. if (pdevOEM->iPaperSize < 0 || pdevOEM->iPaperSize >= MAX_PAPERS)
  737. return FALSE;
  738. if (!(pdevOEM->iUnitScale))
  739. return FALSE;
  740. iPaperSizeID
  741. = pdevOEM->pPaperSize[pdevOEM->iPaperSize].iPaperSizeID;
  742. if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
  743. "\x1B\x26\x6C%c%c\x41",
  744. LOBYTE(iPaperSizeID), HIBYTE(iPaperSizeID))))
  745. return FALSE;
  746. WRITESPOOLBUF(pdevobj, bCmd, (DWORD)(pCmd - bCmd));
  747. iPageLength
  748. = pdevOEM->pPaperSize[pdevOEM->iPaperSize].iLogicalPageHeight;
  749. iPageLength /= pdevOEM->iUnitScale;
  750. if (FAILED(StringCchPrintfExA(bCmd, sizeof bCmd, &pCmd, NULL, 0,
  751. "\x1B\x26\x6C%c%c\x50",
  752. LOBYTE(iPageLength), HIBYTE(iPageLength))))
  753. return FALSE;
  754. WRITESPOOLBUF(pdevobj, bCmd, (DWORD)(pCmd - bCmd));
  755. // # of raster lines in logical page.
  756. pdevOEM->wRasterCount = (WORD)iPageLength;
  757. // Determine dither methods.
  758. pdevOEM->iDither = DITHER_HIGH_DIV2;
  759. if (!(pdevOEM->fRequestColor)) {
  760. pdevOEM->iTextQuality = CMDID_TEXTQUALITY_GRAY;
  761. }
  762. else {
  763. if (!(bTextQuality(pdevobj))){
  764. ERR((DLLTEXT("bTextQuality failed\n")));
  765. return FALSE;
  766. }
  767. }
  768. // Initialize dither tables
  769. if (!(bInitialDither(pdevobj))){
  770. ERR((DLLTEXT("bInitialDither failed\n")));
  771. return FALSE;
  772. }
  773. // Pre-processing of color conversion. needed only photo.
  774. if (pdevOEM->iTextQuality == CMDID_TEXTQUALITY_PHOTO ) {
  775. if (!(bInitialColorConvert(pdevobj)) ){
  776. ERR((DLLTEXT("bInitialColorConvert failed\n")));
  777. return FALSE;
  778. }
  779. }
  780. // Start Raster Data Transfer
  781. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x00\x41", 5);
  782. if ( pdevOEM->fRequestColor ) {
  783. // Open temporary files. One file per one plain.
  784. for (iPlane = 0; iPlane < 4; iPlane++) {
  785. #if !CACHE_FIRST_PLANE
  786. // We do not spool 1st plane
  787. if (0 == iPlane) {
  788. pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
  789. continue;
  790. }
  791. #endif // !CACHE_FIRST_PLANE
  792. if (!MDP_CreateTempFile(pdevobj, pdevOEM, iPlane))
  793. return FALSE;
  794. }
  795. }
  796. else {
  797. for (iPlane = 0; iPlane < 4; iPlane++) {
  798. pdevOEM->TempFile[iPlane] = INVALID_HANDLE_VALUE;
  799. }
  800. }
  801. // Change printer emulation state.
  802. pdevOEM->iEmulState = EMUL_DATA_TRANSFER;
  803. pdevOEM->iCompMode[0] = pdevOEM->iCompMode[1] = pdevOEM->iCompMode[2]
  804. = pdevOEM->iCompMode[3] = COMP_NONE;
  805. // Misc setup.
  806. pdevOEM->y = 0;
  807. if (!pdevOEM->fRequestColor) {
  808. WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x01\x72", 5);
  809. }
  810. pdevOEM->pRasterC = NULL;
  811. pdevOEM->pRasterM = NULL;
  812. pdevOEM->pRasterY = NULL;
  813. pdevOEM->pRasterK = NULL;
  814. for (iPlane = 0; iPlane < 4; iPlane++) {
  815. pdevOEM->wRasterOffset[iPlane] = 0;
  816. // Set color ID for each plane.
  817. // Negative value = Has no ink so do not have to ouput
  818. // Positive value = Has ink on the plane. Have to output.
  819. //
  820. iColor = GetPlaneColor(pdevobj, pdevOEM, iPlane);
  821. pdevOEM->PlaneColor[iPlane] = (-iColor);
  822. switch (iColor) {
  823. // NTRAID#NTBUG9-644657-2002/04/09-yasuho-: AV occured on OEMFilterGraphics()
  824. // If the GetPlaneColor() failed, this function must return as failure.
  825. default:
  826. return FALSE;
  827. case CYAN:
  828. pdevOEM->pRasterC = pdevOEM->pRaster[iPlane];
  829. break;
  830. case MAGENTA:
  831. pdevOEM->pRasterM = pdevOEM->pRaster[iPlane];
  832. break;
  833. case YELLOW:
  834. pdevOEM->pRasterY = pdevOEM->pRaster[iPlane];
  835. break;
  836. case BLACK:
  837. pdevOEM->pRasterK = pdevOEM->pRaster[iPlane];
  838. break;
  839. }
  840. }
  841. return TRUE;
  842. }
  843. BOOL
  844. MDP_EndPage(
  845. PDEVOBJ pdevobj,
  846. PCURRENTSTATUS pdevOEM)
  847. {
  848. INT i;
  849. HANDLE hToken = NULL;
  850. BOOL bRet = FALSE;
  851. // Spooled data transfer
  852. if ( pdevOEM->fRequestColor )
  853. SPOOLOUT(pdevobj);
  854. // End Raster Transfer, FF.
  855. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x43\x0C", 5);
  856. // Change printer emulation state.
  857. pdevOEM->iEmulState = EMUL_RGL;
  858. // Close cache files.
  859. for (i = 0; i < 4; i++) {
  860. if (INVALID_HANDLE_VALUE != pdevOEM->TempFile[i]) {
  861. if (0 == CloseHandle(pdevOEM->TempFile[i])) {
  862. ERR((DLLTEXT("CloseHandle error %d\n"),
  863. GetLastError()));
  864. goto out;
  865. }
  866. pdevOEM->TempFile[i] = INVALID_HANDLE_VALUE;
  867. if (!(hToken = RevertToPrinterSelf()))
  868. goto out;
  869. if (0 == DeleteFile(pdevOEM->TempName[i])) {
  870. ERR((DLLTEXT("DeleteName error %d\n"),
  871. GetLastError()));
  872. goto out;
  873. }
  874. pdevOEM->TempName[i][0] = __TEXT('\0');
  875. (void)ImpersonatePrinterClient(hToken);
  876. hToken = NULL;
  877. }
  878. }
  879. bRet = TRUE;
  880. out:
  881. if (hToken) (void)ImpersonatePrinterClient(hToken);
  882. return bRet;
  883. }
  884. INT APIENTRY
  885. OEMCommandCallback(
  886. PDEVOBJ pdevobj,
  887. DWORD dwCmdCbID,
  888. DWORD dwCount,
  889. PDWORD pdwParams)
  890. {
  891. PCURRENTSTATUS lpnp;
  892. WORD len;
  893. WORD wPageLength;
  894. WORD wVerticalOffset;
  895. WORD wRealOffset;
  896. INT iRet;
  897. VERBOSE((DLLTEXT("OEMCommandCallback(%d) entry.\n"),dwCmdCbID));
  898. lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  899. iRet = 0;
  900. switch ( dwCmdCbID ){
  901. case CMDID_PAPERSOURCE_CSF:
  902. // \x1B&l\x03\x00H
  903. lpnp->iPaperSource = CMDID_PAPERSOURCE_CSF;
  904. break;
  905. case CMDID_PAPERSOURCE_MANUAL:
  906. // \x1B&l\x02\x00H
  907. lpnp->iPaperSource = CMDID_PAPERSOURCE_MANUAL;
  908. break;
  909. case CMDID_PAPERQUALITY_PPC_NORMAL:
  910. case CMDID_PAPERQUALITY_PPC_FINE:
  911. case CMDID_PAPERQUALITY_OHP_NORMAL:
  912. case CMDID_PAPERQUALITY_OHP_FINE:
  913. case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
  914. case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
  915. case CMDID_PAPERQUALITY_IRON_PPC:
  916. case CMDID_PAPERQUALITY_IRON_OHP:
  917. case CMDID_PAPERQUALITY_THICK:
  918. case CMDID_PAPERQUALITY_POSTCARD:
  919. case CMDID_PAPERQUALITY_HIGRADE:
  920. case CMDID_PAPERQUALITY_BACKPRINTFILM:
  921. case CMDID_PAPERQUALITY_LABECA_SHEET:
  922. case CMDID_PAPERQUALITY_CD_MASTER:
  923. case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
  924. case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
  925. case CMDID_PAPERQUALITY_GLOSSY_PAPER:
  926. case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
  927. case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
  928. {
  929. switch ( dwCmdCbID ){
  930. case CMDID_PAPERQUALITY_PPC_NORMAL:
  931. WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x00M", 6);
  932. lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_NORMAL;
  933. break;
  934. case CMDID_PAPERQUALITY_PPC_FINE: // only mono color
  935. if( lpnp->fRequestColor ){
  936. // If user selects color, then we selects PPC NORMAL
  937. // because, PPC FINE is not accepted color
  938. WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x00M", 6);
  939. lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_NORMAL;
  940. }else{
  941. WRITESPOOLBUF(pdevobj, "\x1B&l\x00\x02M", 6);
  942. lpnp->iPaperQuality = CMDID_PAPERQUALITY_PPC_FINE;
  943. }
  944. break;
  945. case CMDID_PAPERQUALITY_OHP_NORMAL:
  946. WRITESPOOLBUF(pdevobj, "\x1B&l\x08\x01M", 6);
  947. lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_NORMAL;
  948. break;
  949. case CMDID_PAPERQUALITY_OHP_FINE:
  950. WRITESPOOLBUF(pdevobj, "\x1B&l\x08\x02M", 6);
  951. lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_FINE;
  952. break;
  953. case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
  954. WRITESPOOLBUF(pdevobj, "\x1B&l\x01\x01M", 6);
  955. lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_EXCL_NORMAL;
  956. break;
  957. case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
  958. WRITESPOOLBUF(pdevobj, "\x1B&l\x01\x02M", 6);
  959. lpnp->iPaperQuality = CMDID_PAPERQUALITY_OHP_EXCL_FINE;
  960. break;
  961. case CMDID_PAPERQUALITY_IRON_PPC:
  962. WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x02M", 6);
  963. lpnp->iPaperQuality = CMDID_PAPERQUALITY_IRON_PPC;
  964. break;
  965. case CMDID_PAPERQUALITY_IRON_OHP:
  966. WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x01M", 6);
  967. lpnp->iPaperQuality = CMDID_PAPERQUALITY_IRON_OHP;
  968. break;
  969. case CMDID_PAPERQUALITY_THICK:
  970. WRITESPOOLBUF(pdevobj, "\x1B&l\x05\x00M", 6);
  971. lpnp->iPaperQuality = CMDID_PAPERQUALITY_THICK;
  972. break;
  973. case CMDID_PAPERQUALITY_POSTCARD:
  974. WRITESPOOLBUF(pdevobj, "\x1B&l\x06\x00M", 6);
  975. lpnp->iPaperQuality = CMDID_PAPERQUALITY_POSTCARD;
  976. break;
  977. case CMDID_PAPERQUALITY_HIGRADE:
  978. WRITESPOOLBUF(pdevobj, "\x1B&l\x07\x00M", 6);
  979. lpnp->iPaperQuality = CMDID_PAPERQUALITY_HIGRADE;
  980. break;
  981. case CMDID_PAPERQUALITY_BACKPRINTFILM:
  982. WRITESPOOLBUF(pdevobj, "\x1B&l\x09\x00M", 6);
  983. lpnp->iPaperQuality = CMDID_PAPERQUALITY_BACKPRINTFILM;
  984. break;
  985. case CMDID_PAPERQUALITY_LABECA_SHEET:
  986. WRITESPOOLBUF(pdevobj, "\x1B&l\x03\x00M", 6);
  987. lpnp->iPaperQuality = CMDID_PAPERQUALITY_LABECA_SHEET;
  988. break;
  989. case CMDID_PAPERQUALITY_CD_MASTER:
  990. WRITESPOOLBUF(pdevobj, "\x1B&l\x04\x01M", 6);
  991. lpnp->iPaperQuality = CMDID_PAPERQUALITY_CD_MASTER;
  992. break;
  993. case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
  994. WRITESPOOLBUF(pdevobj, "\x1B&l\x0A\x00M", 6);
  995. lpnp->iPaperQuality = CMDID_PAPERQUALITY_DYE_SUB_PAPER;
  996. break;
  997. case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
  998. WRITESPOOLBUF(pdevobj, "\x1B&l\x0C\x00M", 6);
  999. lpnp->iPaperQuality = CMDID_PAPERQUALITY_DYE_SUB_LABEL;
  1000. break;
  1001. case CMDID_PAPERQUALITY_GLOSSY_PAPER:
  1002. WRITESPOOLBUF(pdevobj, "\x1B&l\x0F\x00M", 6);
  1003. lpnp->iPaperQuality = CMDID_PAPERQUALITY_GLOSSY_PAPER;
  1004. break;
  1005. case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
  1006. WRITESPOOLBUF(pdevobj, "\x1B&l\x10\x00M", 6);
  1007. lpnp->iPaperQuality = CMDID_PAPERQUALITY_VD_PHOTO_FILM;
  1008. break;
  1009. case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
  1010. WRITESPOOLBUF(pdevobj, "\x1B&l\x11\x00M", 6);
  1011. lpnp->iPaperQuality = CMDID_PAPERQUALITY_VD_PHOTO_CARD;
  1012. break;
  1013. }
  1014. if (lpnp->iPaperSource == CMDID_PAPERSOURCE_MANUAL){
  1015. WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x00H", 6);
  1016. } else {
  1017. // Check if this media ( PAPERQUALITY ) and this
  1018. // paper size is printable on CSF.
  1019. if (IsAsfOkMedia(pdevobj)){
  1020. WRITESPOOLBUF(pdevobj, "\x1B&l\x03\x00H", 6);
  1021. }else{
  1022. WRITESPOOLBUF(pdevobj, "\x1B&l\x02\x00H", 6);
  1023. }
  1024. }
  1025. if( lpnp->fRequestColor ){
  1026. // YMCK Page Plane
  1027. WRITESPOOLBUF(pdevobj, "\x1B\x2A\x72\x04\x55", 5);
  1028. }else{
  1029. // Black Raster Plane
  1030. WRITESPOOLBUF( pdevobj, "\x1B\x2A\x72\x00\x55", 5);
  1031. }
  1032. }
  1033. break;
  1034. case CMDID_TEXTQUALITY_PHOTO:
  1035. case CMDID_TEXTQUALITY_GRAPHIC:
  1036. case CMDID_TEXTQUALITY_CHARACTER:
  1037. lpnp->iTextQuality = dwCmdCbID;
  1038. break;
  1039. // ####
  1040. case CMDID_MIRROR_ON:
  1041. lpnp->bXflip = TRUE;
  1042. break;
  1043. case CMDID_MIRROR_OFF:
  1044. lpnp->bXflip = FALSE;
  1045. break;
  1046. case CMDID_CURSOR_RELATIVE:
  1047. if (dwCount < 1 || !pdwParams)
  1048. break;
  1049. if (!lpnp->iUnitScale)
  1050. break;
  1051. // this printer's linespacing cmd is influenced with current resolution.
  1052. wVerticalOffset = (WORD)(pdwParams[0]);
  1053. wVerticalOffset /= (WORD)lpnp->iUnitScale;
  1054. lpnp->wRasterOffset[0] += wVerticalOffset;
  1055. lpnp->wRasterOffset[1] += wVerticalOffset;
  1056. lpnp->wRasterOffset[2] += wVerticalOffset;
  1057. lpnp->wRasterOffset[3] += wVerticalOffset;
  1058. lpnp->wRasterCount -= wVerticalOffset;
  1059. // Return offset change in device's units
  1060. iRet = wVerticalOffset;
  1061. break;
  1062. case CMDID_RESOLUTION_1200_MONO:
  1063. lpnp->iCurrentResolution = DPI1200;
  1064. lpnp->iUnitScale = 2;
  1065. break;
  1066. case CMDID_RESOLUTION_600:
  1067. lpnp->iCurrentResolution = DPI600;
  1068. lpnp->iUnitScale = 2;
  1069. break;
  1070. case CMDID_RESOLUTION_300:
  1071. lpnp->iCurrentResolution = DPI300;
  1072. lpnp->iUnitScale = 4;
  1073. break;
  1074. case CMDID_PSIZE_LETTER:
  1075. lpnp->iPaperSize = PAPER_SIZE_LETTER;
  1076. break;
  1077. case CMDID_PSIZE_LEGAL:
  1078. lpnp->iPaperSize = PAPER_SIZE_LEGAL;
  1079. break;
  1080. case CMDID_PSIZE_EXECTIVE:
  1081. lpnp->iPaperSize = PAPER_SIZE_EXECTIVE;
  1082. break;
  1083. case CMDID_PSIZE_A4:
  1084. lpnp->iPaperSize = PAPER_SIZE_A4;
  1085. break;
  1086. case CMDID_PSIZE_B5:
  1087. lpnp->iPaperSize = PAPER_SIZE_B5;
  1088. break;
  1089. case CMDID_PSIZE_POSTCARD:
  1090. lpnp->iPaperSize = PAPER_SIZE_POSTCARD;
  1091. break;
  1092. case CMDID_PSIZE_POSTCARD_DOUBLE:
  1093. lpnp->iPaperSize = PAPER_SIZE_DOUBLE_POSTCARD;
  1094. break;
  1095. case CMDID_PSIZE_PHOTO_COLOR_LABEL:
  1096. lpnp->iPaperSize = PAPER_PHOTO_COLOR_LABEL;
  1097. break;
  1098. case CMDID_PSIZE_GLOSSY_LABEL:
  1099. lpnp->iPaperSize = PAPER_GLOSSY_LABEL;
  1100. break;
  1101. case CMDID_PSIZE_CD_MASTER:
  1102. lpnp->iPaperSize = PAPER_CD_MASTER;
  1103. break;
  1104. case CMDID_PSIZE_VD_PHOTO_POSTCARD:
  1105. lpnp->iPaperSize = PAPER_VD_PHOTO_POSTCARD;
  1106. break;
  1107. case CMDID_COLORMODE_COLOR:
  1108. case CMDID_COLORMODE_MONO:
  1109. lpnp->fRequestColor = (dwCmdCbID == CMDID_COLORMODE_COLOR);
  1110. break;
  1111. case CMDID_BEGINDOC_MD5000: // Postcard printable area is expantioned on MD-5000
  1112. lpnp->pPaperSize[PAPER_SIZE_POSTCARD].iLogicalPageHeight
  1113. = 3082 * 2;
  1114. lpnp->pPaperSize[PAPER_SIZE_DOUBLE_POSTCARD].iLogicalPageHeight
  1115. = 3082 * 2;
  1116. case CMDID_BEGINDOC_MD2000:
  1117. case CMDID_BEGINDOC_MD2010:
  1118. lpnp->iModel = dwCmdCbID;
  1119. MDP_StartDoc(pdevobj, MINIDEV_DATA(pdevobj));
  1120. break;
  1121. case CMDID_ENDDOC:
  1122. MDP_EndDoc(pdevobj, MINIDEV_DATA(pdevobj));
  1123. break;
  1124. case CMDID_BEGINPAGE:
  1125. MDP_StartPage(pdevobj, MINIDEV_DATA(pdevobj));
  1126. break;
  1127. case CMDID_ENDPAGE:
  1128. MDP_EndPage(pdevobj, MINIDEV_DATA(pdevobj));
  1129. break;
  1130. default:
  1131. ERR((DLLTEXT("Unknown CallbackID = %d\n"), dwCmdCbID));
  1132. }
  1133. return iRet;
  1134. }
  1135. /*************************** Function Header *******************************
  1136. * IsAsfOkMedia
  1137. *
  1138. * Check if the media and the paper size is printable on Cut Sheet Feeder.
  1139. *
  1140. * HISTORY:
  1141. * 24 Sep 1996 -by- Sueya Sugihara [sueyas]
  1142. * Created.
  1143. *
  1144. ***************************************************************************/
  1145. BOOL IsAsfOkMedia(
  1146. PDEVOBJ pdevobj)
  1147. {
  1148. PCURRENTSTATUS lpnp;
  1149. lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
  1150. if (lpnp->iPaperQuality < CMDID_PAPERQUALITY_FIRST ||
  1151. lpnp->iPaperQuality > CMDID_PAPERQUALITY_LAST)
  1152. return FALSE;
  1153. if (lpnp->iPaperSize < 0 || lpnp->iPaperSize > MAX_PAPERS)
  1154. return FALSE;
  1155. // ASF enabled only with ASF-allowed paper size AND
  1156. // ASF-allowed media type
  1157. if (gMediaType[lpnp->iPaperQuality - CMDID_PAPERQUALITY_FIRST].bAsfOk
  1158. && lpnp->pPaperSize[lpnp->iPaperSize].bAsfOk) {
  1159. return TRUE;
  1160. }
  1161. return FALSE;
  1162. }
  1163. /*************************** Function Header *******************************
  1164. * bTextQuality
  1165. *
  1166. * Select dither table according to the paper quality(Media Type) and
  1167. * resolution and the requested halftoning type.
  1168. * If appropriate halftoning type is not selected, then this function
  1169. * selects halftoning type.
  1170. *
  1171. * HISTORY:
  1172. * 24 Sep 1996 -by- Sueya Sugihara [sueyas]
  1173. * Created.
  1174. *
  1175. ***************************************************************************/
  1176. BOOL bTextQuality(
  1177. PDEVOBJ pdevobj)
  1178. {
  1179. PCURRENTSTATUS lpnp;
  1180. lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
  1181. switch ( lpnp->iPaperQuality ){
  1182. case CMDID_PAPERQUALITY_PPC_NORMAL:
  1183. case CMDID_PAPERQUALITY_OHP_NORMAL:
  1184. case CMDID_PAPERQUALITY_OHP_EXCL_NORMAL:
  1185. case CMDID_PAPERQUALITY_OHP_EXCL_FINE:
  1186. case CMDID_PAPERQUALITY_IRON_PPC:
  1187. case CMDID_PAPERQUALITY_IRON_OHP:
  1188. case CMDID_PAPERQUALITY_THICK:
  1189. case CMDID_PAPERQUALITY_POSTCARD:
  1190. case CMDID_PAPERQUALITY_HIGRADE:
  1191. case CMDID_PAPERQUALITY_BACKPRINTFILM:
  1192. case CMDID_PAPERQUALITY_LABECA_SHEET:
  1193. case CMDID_PAPERQUALITY_CD_MASTER:
  1194. case CMDID_PAPERQUALITY_GLOSSY_PAPER:
  1195. if ( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO ){
  1196. lpnp->iDither = DITHER_HIGH; // 145LPI
  1197. }else if ( lpnp->iTextQuality == CMDID_TEXTQUALITY_GRAPHIC ){
  1198. lpnp->iDither = DITHER_LOW; // 95LPI
  1199. }else{
  1200. lpnp->iDither = DITHER_HIGH_DIV2; // 145/2LPI
  1201. }
  1202. break;
  1203. case CMDID_PAPERQUALITY_DYE_SUB_PAPER:
  1204. case CMDID_PAPERQUALITY_DYE_SUB_LABEL:
  1205. lpnp->iDither = DITHER_DYE; // Dye-sub Media dither
  1206. break;
  1207. case CMDID_PAPERQUALITY_VD_PHOTO_FILM:
  1208. case CMDID_PAPERQUALITY_VD_PHOTO_CARD:
  1209. lpnp->iDither = DITHER_VD; // Dye-sub Media dither
  1210. break;
  1211. default:
  1212. return FALSE;
  1213. }
  1214. return TRUE;
  1215. }
  1216. BOOL
  1217. bDataSpool(
  1218. PDEVOBJ pdevobj,
  1219. HANDLE hFile,
  1220. LPSTR lpBuf,
  1221. DWORD dwLen)
  1222. {
  1223. DWORD dwTemp, dwTemp2;
  1224. BYTE *pTemp;
  1225. if (hFile != INVALID_HANDLE_VALUE) {
  1226. pTemp = lpBuf;
  1227. dwTemp = dwLen;
  1228. while (dwTemp > 0) {
  1229. if (0 == WriteFile(hFile, pTemp, dwTemp, &dwTemp2, NULL)) {
  1230. ERR((DLLTEXT("Writing cache faild, WriteFile() error %d.\n"),
  1231. GetLastError()));
  1232. return FALSE;
  1233. }
  1234. pTemp += dwTemp2;
  1235. dwTemp -= dwTemp2;
  1236. }
  1237. }
  1238. else {
  1239. WRITESPOOLBUF(pdevobj, lpBuf, dwLen);
  1240. }
  1241. return TRUE;
  1242. }
  1243. BOOL
  1244. bSpoolOut(
  1245. PDEVOBJ pdevobj)
  1246. {
  1247. PCURRENTSTATUS lpnp;
  1248. INT iPlane, iColor, iFile;
  1249. DWORD dwSize, dwTemp, dwTemp2;
  1250. HANDLE hFile;
  1251. #define BUF_SIZE 1024
  1252. BYTE Buf[BUF_SIZE];
  1253. lpnp = (PCURRENTSTATUS)(MINIDEV_DATA(pdevobj));
  1254. VERBOSE((DLLTEXT("bSpoolOut entry.\n")));
  1255. for (iPlane = 0; iPlane < 4; iPlane++) {
  1256. // CMDID_PAPERQUALITY_OHP_EXCL_NORMAL : MCY
  1257. // CMDID_PAPERQUALITY_OHP_EXCL_FINE : MCY
  1258. // CMDID_PAPERQUALITY_IRON_OHP : YMC
  1259. // Except above : CMYK
  1260. VERBOSE((DLLTEXT("About to send plane %d.\n"), iPlane));
  1261. // Check if we have ink in this plane.
  1262. iColor = lpnp->PlaneColor[iPlane];
  1263. // Exit loop if no remaining plane to print
  1264. if (iColor == NONE) {
  1265. VERBOSE((DLLTEXT("No remaining plane left.\n")));
  1266. break;
  1267. }
  1268. else if (0 > iColor) {
  1269. VERBOSE((DLLTEXT("No ink on this plane.\n")));
  1270. continue;
  1271. }
  1272. // If it is 2nd plane and after, send Back Feed.
  1273. if (0 < iPlane) {
  1274. WRITESPOOLBUF(pdevobj, "\x1B\x1A\x00\x00\x0C", 5);
  1275. }
  1276. VERBOSE((DLLTEXT("Cached data Plane=%d Color=%d\n"),
  1277. iPlane, iColor));
  1278. // Get file handle.
  1279. hFile = lpnp->TempFile[iPlane];
  1280. if (INVALID_HANDLE_VALUE == hFile) {
  1281. #if CACHE_FIRST_PLANE
  1282. ERR((DLLTEXT("file handle NULL in SendCachedData.\n")));
  1283. return FALSE;
  1284. #endif // CACHE_FIRST_PLANE
  1285. // Allow fp to be NULL for the case where we
  1286. // immediately send data to printer.
  1287. continue;
  1288. }
  1289. dwSize = SetFilePointer(hFile, 0L, NULL, FILE_CURRENT);
  1290. if (0xffffffff == dwSize) {
  1291. ERR((DLLTEXT("SetFilePointer failed %d\n"),
  1292. GetLastError()));
  1293. return FALSE;
  1294. }
  1295. // Output cached data.
  1296. if (0L != SetFilePointer(hFile, 0L, NULL, FILE_BEGIN)) {
  1297. ERR((DLLTEXT("SetFilePointer failed %d\n"),
  1298. GetLastError()));
  1299. return FALSE;
  1300. }
  1301. VERBOSE((DLLTEXT("Size of data to be read and sent = %ld\n"), dwSize));
  1302. for ( ; dwSize > 0; dwSize -= dwTemp2) {
  1303. dwTemp = ((BUF_SIZE < dwSize) ? BUF_SIZE : dwSize);
  1304. if (0 == ReadFile(hFile, Buf, dwTemp, &dwTemp2, NULL)) {
  1305. ERR((DLLTEXT("ReadFile error in SendCachedData.\n")));
  1306. return FALSE;
  1307. }
  1308. if (dwTemp2 > 0) {
  1309. WRITESPOOLBUF(pdevobj, Buf, dwTemp2);
  1310. }
  1311. }
  1312. }
  1313. return TRUE;
  1314. }
  1315. /*++
  1316. Routine Name
  1317. ImpersonationToken
  1318. Routine Description:
  1319. This routine checks if a token is a primary token or an impersonation
  1320. token.
  1321. Arguments:
  1322. hToken - impersonation token or primary token of the process
  1323. Return Value:
  1324. TRUE, if the token is an impersonation token
  1325. FALSE, otherwise.
  1326. --*/
  1327. BOOL
  1328. ImpersonationToken(
  1329. IN HANDLE hToken
  1330. )
  1331. {
  1332. BOOL bRet = TRUE;
  1333. TOKEN_TYPE eTokenType;
  1334. DWORD cbNeeded;
  1335. DWORD LastError;
  1336. //
  1337. // Preserve the last error. Some callers of ImpersonatePrinterClient (which
  1338. // calls ImpersonationToken) rely on the fact that ImpersonatePrinterClient
  1339. // does not alter the last error.
  1340. //
  1341. LastError = GetLastError();
  1342. //
  1343. // Get the token type from the thread token. The token comes
  1344. // from RevertToPrinterSelf. An impersonation token cannot be
  1345. // queried, because RevertToPRinterSelf doesn't open it with
  1346. // TOKEN_QUERY access. That's why we assume that hToken is
  1347. // an impersonation token by default
  1348. //
  1349. if (GetTokenInformation(hToken,
  1350. TokenType,
  1351. &eTokenType,
  1352. sizeof(eTokenType),
  1353. &cbNeeded))
  1354. {
  1355. bRet = eTokenType == TokenImpersonation;
  1356. }
  1357. SetLastError(LastError);
  1358. return bRet;
  1359. }
  1360. /*++
  1361. Routine Name
  1362. RevertToPrinterSelf
  1363. Routine Description:
  1364. This routine will revert to the local system. It returns the token that
  1365. ImpersonatePrinterClient then uses to imersonate the client again. If the
  1366. current thread doesn't impersonate, then the function merely returns the
  1367. primary token of the process. (instead of returning NULL) Thus we honor
  1368. a request for reverting to printer self, even if the thread is not impersonating.
  1369. Arguments:
  1370. None.
  1371. Return Value:
  1372. NULL, if the function failed
  1373. HANDLE to token, otherwise.
  1374. --*/
  1375. HANDLE
  1376. RevertToPrinterSelf(
  1377. VOID
  1378. )
  1379. {
  1380. HANDLE NewToken, OldToken, cToken;
  1381. BOOL Status;
  1382. NewToken = NULL;
  1383. Status = OpenThreadToken(GetCurrentThread(),
  1384. TOKEN_IMPERSONATE,
  1385. TRUE,
  1386. &OldToken);
  1387. if (Status)
  1388. {
  1389. //
  1390. // We are currently impersonating
  1391. //
  1392. cToken = GetCurrentThread();
  1393. Status = SetThreadToken(&cToken,
  1394. NewToken);
  1395. if (!Status) {
  1396. return NULL;
  1397. }
  1398. }
  1399. else if (GetLastError() == ERROR_NO_TOKEN)
  1400. {
  1401. //
  1402. // We are not impersonating
  1403. //
  1404. Status = OpenProcessToken(GetCurrentProcess(),
  1405. TOKEN_QUERY,
  1406. &OldToken);
  1407. if (!Status) {
  1408. return NULL;
  1409. }
  1410. }
  1411. return OldToken;
  1412. }
  1413. /*++
  1414. Routine Name
  1415. ImpersonatePrinterClient
  1416. Routine Description:
  1417. This routine attempts to set the passed in hToken as the token for the
  1418. current thread. If hToken is not an impersonation token, then the routine
  1419. will simply close the token.
  1420. Arguments:
  1421. hToken - impersonation token or primary token of the process
  1422. Return Value:
  1423. TRUE, if the function succeeds in setting hToken
  1424. FALSE, otherwise.
  1425. --*/
  1426. BOOL
  1427. ImpersonatePrinterClient(
  1428. HANDLE hToken)
  1429. {
  1430. BOOL Status;
  1431. HANDLE cToken;
  1432. //
  1433. // Check if we have an impersonation token
  1434. //
  1435. if (ImpersonationToken(hToken))
  1436. {
  1437. cToken = GetCurrentThread();
  1438. Status = SetThreadToken(&cToken,
  1439. hToken);
  1440. if (!Status)
  1441. {
  1442. return FALSE;
  1443. }
  1444. }
  1445. CloseHandle(hToken);
  1446. return TRUE;
  1447. }