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.

378 lines
12 KiB

  1. /*
  2. * spool.c - WritePrinter hook.
  3. *
  4. * Need to be manipulate the spooler data for Canon CPCA architecture.
  5. */
  6. #include "pdev.h"
  7. // NTRAID#NTBUG9-172276-2002/03/08-yasuho-: CPCA support
  8. #define MAX_CPCA_PACKET_SIZE 4096 // Must be <= 64KB-1
  9. // CPCA Operation codes
  10. #define CPCA_JobStart 0x0011
  11. #define CPCA_JobEnd 0x0013
  12. #define CPCA_BinderStart 0x0014
  13. #define CPCA_SetBinder 0x0015
  14. #define CPCA_BinderEnd 0x0016
  15. #define CPCA_DocumentStart 0x0017
  16. #define CPCA_SetDocument 0x0018
  17. #define CPCA_DocumentEnd 0x0019
  18. #define CPCA_Send 0x001A
  19. #define CPCA_ExecutiveMethod 0x001D
  20. // CPCA Flags
  21. #define F_Cont 0x02
  22. // CPCA Attributes
  23. #define ATT_DOCFORMAT 0x002E
  24. #define DOCFORMAT_LIPS 0x27
  25. #define ATT_RESOLUTION 0x003A
  26. #define RESOLUTION_QUICK 0x05
  27. #define RESOLUTION_FINE 0x06
  28. #define RESOLUTION_SUPERFINE 0x07
  29. #define ATT_COPIES 0x07D7
  30. #define ATT_OUTPUT 0x07D8
  31. #define OUTPUT_NO_COLLATE 0x08
  32. #define OUTPUT_COLLATE 0x0B
  33. #define OUTPUT_GROUP_COLLATE 0x0F
  34. #define ATT_OUTPUTBIN 0x07D9
  35. #define OUTPUTBIN_FACEUP 0x01
  36. #define OUTPUTBIN_FACEDOWN 0x02
  37. #define OUTPUTBIN_SORT 0x11
  38. #define OUTPUTBIN_NUMBER 0x12
  39. #define OUTPUTBIN_STACK 0x15
  40. #define ATT_FINISHING 0x07DA
  41. #define FINISHING_STAPLE 0x0C
  42. #define FINISHING_COUNT_1 0x66
  43. #define FINISHING_COUNT_2 0x67
  44. #define ATT_OUTPUTPARTITION 0x084A
  45. #define OUTPART_JOBOFFSET 0x01
  46. #define OUTPART_NONE 0x04
  47. #define ATT_OUTPUTFACE 0x084B
  48. #define OUTPUTFACE_FACEUP 0x01
  49. #define OUTPUTFACE_FACEDOWN 0x02
  50. #define OUTPUTFACE_NONE 0x03
  51. static WORD wStapleModes[] = {
  52. 0x00CA, // top_left
  53. 0x00D5, // top
  54. 0x00CC, // top_right
  55. 0x00D3, // left
  56. 0x00EE, // center (NOT USED)
  57. 0x00D4, // right
  58. 0x00CB, // bottom_left
  59. 0x00D6, // bottom
  60. 0x00CD, // bottom_right
  61. };
  62. extern LIPSCmd cmdEndDoc4;
  63. extern LIPSCmd cmdEndDoc4C;
  64. /*
  65. * FlushCPCABuffer
  66. */
  67. static BOOL
  68. FlushCPCABuffer(PDEVOBJ pdevobj, PLIPSPDEV pOEM)
  69. {
  70. DWORD dwCount;
  71. if (pOEM->CPCABcount == 0)
  72. return TRUE;
  73. if (!WritePrinter(pdevobj->hPrinter, pOEM->CPCABuf, pOEM->CPCABcount,
  74. &dwCount) || dwCount != pOEM->CPCABcount)
  75. return FALSE;
  76. pOEM->CPCABcount = 0;
  77. return TRUE;
  78. }
  79. /*
  80. * SendCPCAPacket
  81. */
  82. static BOOL
  83. SendCPCAPacket(
  84. PDEVOBJ pdevobj,
  85. WORD wCmd,
  86. BYTE flags,
  87. PBYTE pParams,
  88. WORD nParams)
  89. {
  90. PLIPSPDEV pOEM;
  91. PBYTE pBuf;
  92. DWORD dwCount;
  93. pOEM = (PLIPSPDEV)pdevobj->pdevOEM;
  94. dwCount = pOEM->CPCABcount;
  95. if (dwCount + CPCA_PACKET_SIZE + nParams > CPCA_BUFFER_SIZE) {
  96. if (!FlushCPCABuffer(pdevobj, pOEM))
  97. return FALSE;
  98. // NTRAID#NTBUG9-548450-2002/03/08-yasuho-: possible buffer overrun.
  99. dwCount = 0;
  100. }
  101. pBuf = pOEM->CPCAPKT;
  102. pBuf[3] = flags;
  103. pBuf[4] = HIBYTE(wCmd);
  104. pBuf[5] = LOBYTE(wCmd);
  105. pBuf[8] = HIBYTE(nParams);
  106. pBuf[9] = LOBYTE(nParams);
  107. CopyMemory(&pOEM->CPCABuf[dwCount], pOEM->CPCAPKT, CPCA_PACKET_SIZE);
  108. dwCount += CPCA_PACKET_SIZE;
  109. if (nParams) {
  110. CopyMemory(&pOEM->CPCABuf[dwCount], pParams, nParams);
  111. dwCount += nParams;
  112. }
  113. pOEM->CPCABcount = dwCount;
  114. return TRUE;
  115. }
  116. /*
  117. * CPCAInit
  118. */
  119. VOID
  120. CPCAInit(PLIPSPDEV pOEM)
  121. {
  122. pOEM->CPCAPKT[0] = 0xCD; // Header ID
  123. pOEM->CPCAPKT[1] = 0xCA;
  124. pOEM->CPCAPKT[2] = 0x10; // Version
  125. pOEM->CPCABcount = 0;
  126. }
  127. /*
  128. * CPCAStart
  129. */
  130. VOID
  131. CPCAStart(PDEVOBJ pdevobj)
  132. {
  133. PLIPSPDEV pOEM = (PLIPSPDEV)pdevobj->pdevOEM;
  134. WORD wTemp;
  135. BYTE param[32];
  136. ZeroMemory(param, sizeof param);
  137. param[4] = 0x01;
  138. (VOID)SendCPCAPacket(pdevobj, CPCA_JobStart, 0, param, 13);
  139. // ZeroMemory(param, 4);
  140. (VOID)SendCPCAPacket(pdevobj, CPCA_BinderStart, 0, param, 4);
  141. param[0] = HIBYTE(ATT_COPIES);
  142. param[1] = LOBYTE(ATT_COPIES);
  143. // NTRAID#NTBUG9-501162-2002/03/08-yasuho-: Collate does not work
  144. if (pOEM->sorttype == SORTTYPE_SORT || pOEM->collate == COLLATE_ON) {
  145. param[2] = HIBYTE(pOEM->copies);
  146. param[3] = LOBYTE(pOEM->copies);
  147. } else {
  148. param[2] = 0x00;
  149. param[3] = 0x01;
  150. }
  151. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 4);
  152. // NTRAID#NTBUG9-278671-2002/03/08-yasuho-: Finisher !work
  153. // NTRAID#NTBUG9-293002-2002/03/08-yasuho-:
  154. // Features are different from H/W options.
  155. if (pOEM->fCPCA2) {
  156. param[0] = HIBYTE(ATT_OUTPUT);
  157. param[1] = LOBYTE(ATT_OUTPUT);
  158. param[2] = OUTPUT_COLLATE;
  159. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3);
  160. }
  161. // NTRAID#NTBUG9-203340-2002/03/08-yasuho-:
  162. // Output tray could not selected correctly.
  163. // NTRAID#NTBUG9-293002-2002/03/08-yasuho-:
  164. // Features are different from H/W options.
  165. param[0] = HIBYTE(ATT_OUTPUTBIN);
  166. param[1] = LOBYTE(ATT_OUTPUTBIN);
  167. if (pOEM->tray == INIT || pOEM->tray == 100) {
  168. param[2] = OUTPUTBIN_FACEDOWN;
  169. ZeroMemory(&param[3], 4);
  170. } else if (pOEM->tray == 0) {
  171. param[2] = OUTPUTBIN_STACK;
  172. ZeroMemory(&param[3], 4);
  173. } else if (pOEM->tray == 101) {
  174. param[2] = OUTPUTBIN_FACEUP;
  175. ZeroMemory(&param[3], 4);
  176. } else {
  177. param[2] = OUTPUTBIN_NUMBER;
  178. param[3] = (BYTE)pOEM->tray;
  179. ZeroMemory(&param[4], 3);
  180. }
  181. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7);
  182. if (pOEM->method != INIT) {
  183. // Staple stacker
  184. param[0] = HIBYTE(ATT_OUTPUTPARTITION);
  185. param[1] = LOBYTE(ATT_OUTPUTPARTITION);
  186. param[2] = (pOEM->method == METHOD_JOBOFFSET) ?
  187. OUTPART_JOBOFFSET : OUTPART_NONE;
  188. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3);
  189. param[0] = HIBYTE(ATT_OUTPUTFACE);
  190. param[1] = LOBYTE(ATT_OUTPUTFACE);
  191. param[2] = (pOEM->method == METHOD_FACEUP) ?
  192. OUTPUTFACE_FACEUP : OUTPUTFACE_FACEDOWN;
  193. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3);
  194. if (pOEM->method == METHOD_STAPLE) {
  195. param[0] = HIBYTE(ATT_FINISHING);
  196. param[1] = LOBYTE(ATT_FINISHING);
  197. param[2] = 1;
  198. param[3] = FINISHING_STAPLE;
  199. wTemp = pOEM->staple;
  200. if (wTemp < 0 || wTemp >= 9)
  201. wTemp = 0;
  202. // NTRAID#NTBUG9-292998-2002/03/08-yasuho-: Stapling operate incorrectly.
  203. switch (wTemp) {
  204. default:
  205. param[4] = FINISHING_COUNT_1;
  206. break;
  207. case 1: // top
  208. case 3: // left
  209. case 5: // right
  210. case 7: // center
  211. param[4] = FINISHING_COUNT_2;
  212. break;
  213. }
  214. wTemp = wStapleModes[wTemp];
  215. param[5] = HIBYTE(wTemp);
  216. param[6] = LOBYTE(wTemp);
  217. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7);
  218. } else {
  219. param[0] = HIBYTE(ATT_FINISHING);
  220. param[1] = LOBYTE(ATT_FINISHING);
  221. param[2] = 0;
  222. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 3);
  223. }
  224. } else if (pOEM->sorttype != INIT) {
  225. // Sorter
  226. param[0] = HIBYTE(ATT_OUTPUTBIN);
  227. param[1] = LOBYTE(ATT_OUTPUTBIN);
  228. param[2] = (pOEM->sorttype == SORTTYPE_SORT) ?
  229. OUTPUTBIN_SORT : OUTPUTBIN_STACK;
  230. ZeroMemory(&param[3], 4);
  231. (VOID)SendCPCAPacket(pdevobj, CPCA_SetBinder, 0, param, 7);
  232. }
  233. ZeroMemory(param, 4);
  234. (VOID)SendCPCAPacket(pdevobj, CPCA_DocumentStart, 0, param, 4);
  235. param[0] = HIBYTE(ATT_DOCFORMAT);
  236. param[1] = LOBYTE(ATT_DOCFORMAT);
  237. param[2] = DOCFORMAT_LIPS;
  238. param[3] = 0;
  239. param[4] = 0;
  240. (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 5);
  241. // NTRAID#NTBUG9-244001-2002/03/08-yasuho-: 1200dpi doesn't work on LBP-470.
  242. param[0] = HIBYTE(ATT_RESOLUTION);
  243. param[1] = LOBYTE(ATT_RESOLUTION);
  244. if (pOEM->resolution == 1200)
  245. param[2] = RESOLUTION_SUPERFINE;
  246. else if (pOEM->resolution == 600)
  247. param[2] = RESOLUTION_FINE;
  248. else
  249. param[2] = RESOLUTION_QUICK;
  250. ZeroMemory(&param[3], 4);
  251. (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 7);
  252. param[0] = HIBYTE(ATT_COPIES);
  253. param[1] = LOBYTE(ATT_COPIES);
  254. // NTRAID#NTBUG9-501162-2002/03/08-yasuho-: Collate does not work
  255. if (pOEM->sorttype != SORTTYPE_SORT && pOEM->collate != COLLATE_ON) {
  256. param[2] = HIBYTE(pOEM->copies);
  257. param[3] = LOBYTE(pOEM->copies);
  258. } else {
  259. param[2] = 0x00;
  260. param[3] = 0x01;
  261. }
  262. (VOID)SendCPCAPacket(pdevobj, CPCA_SetDocument, 0, param, 4);
  263. (VOID)FlushCPCABuffer(pdevobj, pOEM);
  264. }
  265. /*
  266. * CPCAEnd
  267. */
  268. VOID
  269. CPCAEnd(PDEVOBJ pdevobj, BOOL fColor)
  270. {
  271. PLIPSPDEV pOEM = (PLIPSPDEV)pdevobj->pdevOEM;
  272. LIPSCmd *pCmd;
  273. BYTE param[32];
  274. param[0] = 0x01;
  275. pCmd = fColor ? &cmdEndDoc4C : &cmdEndDoc4;
  276. CopyMemory(&param[1], pCmd->pCmdStr, pCmd->cbSize);
  277. (VOID)SendCPCAPacket(pdevobj, CPCA_Send, 0, param, pCmd->cbSize + 1);
  278. (VOID)SendCPCAPacket(pdevobj, CPCA_DocumentEnd, 0, NULL, 0);
  279. (VOID)SendCPCAPacket(pdevobj, CPCA_BinderEnd, 0, NULL, 0);
  280. param[0] = 0x00;
  281. (VOID)SendCPCAPacket(pdevobj, CPCA_JobEnd, 0, param, 1);
  282. (VOID)FlushCPCABuffer(pdevobj, pOEM);
  283. }
  284. /*
  285. * OEMWritePrinter
  286. */
  287. BOOL APIENTRY
  288. OEMWritePrinter(
  289. PDEVOBJ pdevobj,
  290. PVOID pBuf,
  291. DWORD cbBuffer,
  292. PDWORD pcbWritten)
  293. {
  294. PLIPSPDEV pOEM;
  295. PBYTE pTemp, pCmd;
  296. DWORD dwSize, dwCount, dwWritten;
  297. WORD wCount;
  298. BYTE cmd[CPCA_PACKET_SIZE+1];
  299. // This is used for UNIDRV to detect the plug-in.
  300. if (pBuf == NULL && cbBuffer == 0)
  301. return TRUE;
  302. pOEM = (PLIPSPDEV)pdevobj->pdevOEM;
  303. // If printer is not CPCA, pass through to the spooler.
  304. if (!pOEM->fCPCA)
  305. return WritePrinter(pdevobj->hPrinter, pBuf, cbBuffer, pcbWritten) &&
  306. cbBuffer == *pcbWritten;
  307. pTemp = (PBYTE)pBuf;
  308. dwSize = cbBuffer;
  309. while (dwSize > 0) {
  310. dwCount = min(dwSize, MAX_CPCA_PACKET_SIZE);
  311. // Build Send packet
  312. pCmd = pOEM->CPCAPKT;
  313. pCmd[3] = F_Cont;
  314. pCmd[4] = HIBYTE(CPCA_Send);
  315. pCmd[5] = LOBYTE(CPCA_Send);
  316. wCount = (WORD)(dwCount + 1);
  317. pCmd[8] = HIBYTE(wCount);
  318. pCmd[9] = LOBYTE(wCount);
  319. CopyMemory(cmd, pOEM->CPCAPKT, CPCA_PACKET_SIZE);
  320. cmd[CPCA_PACKET_SIZE] = 0x01;
  321. if (!WritePrinter(pdevobj->hPrinter, cmd, sizeof cmd, &dwWritten) ||
  322. sizeof cmd != dwWritten)
  323. return FALSE;
  324. if (!WritePrinter(pdevobj->hPrinter, pTemp, dwCount, &dwWritten) ||
  325. dwCount != dwWritten)
  326. return FALSE;
  327. pTemp += dwCount;
  328. dwSize -= dwCount;
  329. }
  330. *pcbWritten = cbBuffer;
  331. return TRUE;
  332. }