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.

517 lines
15 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. escape.c
  5. Abstract:
  6. Implementation of escape related DDI entry points:
  7. DrvEscape
  8. Environment:
  9. Windows NT Unidrv driver
  10. Revision History:
  11. 10/14/96 -amandan-
  12. Initial framework.
  13. 03/31/97 -zhanw-
  14. Added OEM customization support
  15. --*/
  16. #include "unidrv.h"
  17. // define DPRECT if you want to enable DRAWPATTERNRECT escape feature
  18. #define DPRECT
  19. typedef struct _POINTS {
  20. short x;
  21. short y;
  22. } POINTs;
  23. typedef struct _SHORTDRAWPATRECT { // use 16-bit POINT structure
  24. POINTs ptPosition;
  25. POINTs ptSize;
  26. WORD wStyle;
  27. WORD wPattern;
  28. } SHORTDRAWPATRECT, *PSHORTDRAWPATRECT;
  29. ULONG
  30. DrvEscape(
  31. SURFOBJ *pso,
  32. ULONG iEsc,
  33. ULONG cjIn,
  34. PVOID *pvIn,
  35. ULONG cjOut,
  36. PVOID *pvOut
  37. )
  38. /*++
  39. Routine Description:
  40. Implementation of DDI entry point DrvEscape.
  41. Please refer to DDK documentation for more details.
  42. Arguments:
  43. pso - Describes the surface the call is directed to
  44. iEsc - Specifies a query
  45. cjIn - Specifies the size in bytes of the buffer pointed to by pvIn
  46. pvIn - Points to input data buffer
  47. cjOut - Specifies the size in bytes of the buffer pointed to by pvOut
  48. pvOut - Points to the output buffer
  49. Return Value:
  50. Depends on the query specified by iEsc parameter
  51. --*/
  52. {
  53. #define pbIn ((BYTE *)pvIn)
  54. #define pdwIn ((DWORD *)pvIn)
  55. #define pdwOut ((DWORD *)pvOut)
  56. PDEV *pPDev;
  57. ULONG ulRes = 0;
  58. VERBOSE(("Entering DrvEscape: iEsc = %d...\n", iEsc));
  59. ASSERT(pso);
  60. pPDev = (PDEV *) pso->dhpdev;
  61. ASSERT_VALID_PDEV(pPDev);
  62. //
  63. // use driver managed surface
  64. //
  65. if (pPDev->pso)
  66. pso = pPDev->pso;
  67. //
  68. // Handle OEM hooks
  69. //
  70. HANDLE_OEMHOOKS(pPDev,
  71. EP_OEMEscape,
  72. PFN_OEMEscape,
  73. ULONG,
  74. (pso,
  75. iEsc,
  76. cjIn,
  77. pvIn,
  78. cjOut,
  79. pvOut));
  80. HANDLE_VECTORHOOKS(pPDev,
  81. EP_OEMEscape,
  82. VMEscape,
  83. ULONG,
  84. (pso,
  85. iEsc,
  86. cjIn,
  87. pvIn,
  88. cjOut,
  89. pvOut));
  90. switch( iEsc )
  91. {
  92. case QUERYESCSUPPORT:
  93. //
  94. // Check if the specified escape code is supported
  95. //
  96. if (pvIn != NULL || cjIn >= sizeof(DWORD))
  97. {
  98. switch( *pdwIn )
  99. {
  100. case QUERYESCSUPPORT:
  101. case PASSTHROUGH:
  102. //
  103. // Always support these escapes
  104. //
  105. ulRes = 1;
  106. break;
  107. case SETCOPYCOUNT:
  108. ulRes = pPDev->dwMaxCopies > 1;
  109. break;
  110. #ifndef WINNT_40 // NT5
  111. case DRAWPATTERNRECT:
  112. if ((pPDev->fMode & PF_RECT_FILL) &&
  113. (pPDev->dwMinGrayFill < pPDev->dwMaxGrayFill) &&
  114. (pPDev->pdmPrivate->iLayout == ONE_UP) &&
  115. (!(pPDev->pdm->dmFields & DM_TTOPTION) ||
  116. pPDev->pdm->dmTTOption != DMTT_BITMAP) &&
  117. !(pPDev->fMode2 & PF2_MIRRORING_ENABLED) &&
  118. !(pPDev->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS)) // else, only black fill
  119. {
  120. if (pPDev->fMode & PF_RECTWHITE_FILL)
  121. ulRes = 2;
  122. else
  123. ulRes = 1;
  124. }
  125. break;
  126. #endif // !WINNT_40
  127. }
  128. }
  129. break;
  130. case PASSTHROUGH:
  131. //
  132. // QFE fix: NT4 TTY driver compatibility.
  133. // There is an application that sends FF by itself.
  134. // We don't want to send Form Feed if application calls DrvEscape.
  135. //
  136. if (pPDev->bTTY)
  137. {
  138. pPDev->fMode2 |= PF2_PASSTHROUGH_CALLED_FOR_TTY;
  139. }
  140. if( pvIn == NULL || cjIn < sizeof(WORD) )
  141. {
  142. SetLastError( ERROR_INVALID_PARAMETER );
  143. ERR(("DrvEscape(PASSTHROUGH): Bad input parameters\n"));
  144. }
  145. else
  146. {
  147. //
  148. // Win 3.1 actually uses the first 2 bytes as a count of the
  149. // number of bytes following!!!! So, the following union
  150. // allows us to copy the data to an aligned field that
  151. // we use. And thus we ignore cjIn!
  152. //
  153. union
  154. {
  155. WORD wCount;
  156. BYTE bCount[ 2 ];
  157. } u;
  158. u.bCount[ 0 ] = pbIn[ 0 ];
  159. u.bCount[ 1 ] = pbIn[ 1 ];
  160. if( u.wCount && cjIn >= (ULONG)(u.wCount + sizeof(WORD)) )
  161. {
  162. ulRes = WriteSpoolBuf( pPDev, pbIn + 2, u.wCount );
  163. }
  164. else
  165. {
  166. SetLastError( ERROR_INVALID_DATA );
  167. ERR(("DrvEscape: Bad data in PASSTRHOUGH.\n"));
  168. }
  169. }
  170. break;
  171. case SETCOPYCOUNT:
  172. if( pdwIn && *pdwIn > 0 )
  173. {
  174. pPDev->sCopies = (SHORT)*pdwIn;
  175. //
  176. // Check whether the copy count is in printer range
  177. //
  178. if( pPDev->sCopies > (SHORT)pPDev->dwMaxCopies )
  179. pPDev->sCopies = (SHORT)pPDev->dwMaxCopies;
  180. if( pdwOut )
  181. *pdwOut = pPDev->sCopies;
  182. ulRes = 1;
  183. }
  184. break;
  185. case DRAWPATTERNRECT:
  186. {
  187. #ifndef WINNT_40
  188. typedef struct _DRAWPATRECTP {
  189. DRAWPATRECT DrawPatRect;
  190. XFORMOBJ *pXFormObj;
  191. } DRAWPATRECTP, *PDRAWPATRECTP;
  192. if (pvIn == NULL || (cjIn != sizeof(DRAWPATRECT) && cjIn != sizeof(DRAWPATRECTP)))
  193. #else
  194. if( pvIn == NULL || cjIn != sizeof(DRAWPATRECT))
  195. #endif
  196. {
  197. if (pvIn && cjIn == sizeof(SHORTDRAWPATRECT)) // check for Win3.1 DRAWPATRECT size
  198. {
  199. DRAWPATRECT dpr;
  200. PSHORTDRAWPATRECT psdpr = (PSHORTDRAWPATRECT)pvIn;
  201. if (pPDev->fMode & PF_ENUM_GRXTXT)
  202. {
  203. //
  204. // Some apps (Access 2.0, AmiPro 3.1, etc.) do use the 16-bit
  205. // POINT version of DRAWPATRECT structure. Have to be compatible
  206. // with these apps.
  207. //
  208. dpr.ptPosition.x = (LONG)psdpr->ptPosition.x;
  209. dpr.ptPosition.y = (LONG)psdpr->ptPosition.y;
  210. dpr.ptSize.x = (LONG)psdpr->ptSize.x;
  211. dpr.ptSize.y = (LONG)psdpr->ptSize.y;
  212. dpr.wStyle = psdpr->wStyle;
  213. dpr.wPattern = psdpr->wPattern;
  214. ulRes = DrawPatternRect(pPDev, &dpr);
  215. }
  216. }
  217. else
  218. {
  219. SetLastError( ERROR_INVALID_PARAMETER );
  220. ERR(("DrvEscape(DRAWPATTERNRECT): Bad input parameters.\n"));
  221. }
  222. }
  223. else if (pPDev->fMode & PF_ENUM_GRXTXT)
  224. {
  225. DRAWPATRECT dpr = *(PDRAWPATRECT)pvIn;
  226. #ifndef WINNT_40 // NT 5.0
  227. if (pPDev->pdmPrivate->iLayout != ONE_UP && cjIn == sizeof(DRAWPATRECTP))
  228. {
  229. XFORMOBJ *pXFormObj = ((PDRAWPATRECTP)pvIn)->pXFormObj;
  230. POINTL PTOut[2],PTIn[2];
  231. PTIn[0].x = dpr.ptPosition.x + pPDev->rcClipRgn.left;
  232. PTIn[0].y = dpr.ptPosition.y + pPDev->rcClipRgn.top;
  233. PTIn[1].x = PTIn[0].x + dpr.ptSize.x;
  234. PTIn[1].y = PTIn[0].y + dpr.ptSize.y;
  235. if (!XFORMOBJ_bApplyXform(pXFormObj,
  236. XF_LTOL,
  237. 2,
  238. PTIn,
  239. PTOut))
  240. {
  241. ERR (("DrvEscape(DRAWPATTERNRECT): XFORMOBJ_bApplyXform failed.\n"));
  242. break;
  243. }
  244. dpr.ptPosition.x = PTOut[0].x;
  245. dpr.ptSize.x = PTOut[1].x - PTOut[0].x;
  246. if (dpr.ptSize.x < 0)
  247. {
  248. dpr.ptPosition.x += dpr.ptSize.x;
  249. dpr.ptSize.x = -dpr.ptSize.x;
  250. }
  251. else if (dpr.ptSize.x == 0)
  252. dpr.ptSize.x = 1;
  253. dpr.ptPosition.y = PTOut[0].y;
  254. dpr.ptSize.y = PTOut[1].y - PTOut[0].y;
  255. if (dpr.ptSize.y < 0)
  256. {
  257. dpr.ptPosition.y += dpr.ptSize.y;
  258. dpr.ptSize.y = -dpr.ptSize.y;
  259. }
  260. else if (dpr.ptSize.y == 0)
  261. dpr.ptSize.y = 1;
  262. }
  263. #endif // !WINNT_40
  264. // Test whether to force minimum size = 2 pixels
  265. //
  266. if (pPDev->fMode & PF_SINGLEDOT_FILTER)
  267. {
  268. if (dpr.ptSize.y < 2)
  269. dpr.ptSize.y = 2;
  270. if (dpr.ptSize.x < 2)
  271. dpr.ptSize.x = 2;
  272. }
  273. ulRes = DrawPatternRect(pPDev, &dpr);
  274. }
  275. else
  276. ulRes = 1; // no need for GDI to take any action
  277. break; // case DRAWPATTERNRECT
  278. }
  279. default:
  280. SetLastError( ERROR_INVALID_FUNCTION );
  281. break;
  282. }
  283. return ulRes;
  284. }
  285. ULONG
  286. DrawPatternRect(
  287. PDEV *pPDev,
  288. PDRAWPATRECT pPatRect)
  289. /*++
  290. Routine Description:
  291. Implementation of DRAWPATTERNECT escape. Note that it is PCL-specific.
  292. Arguments:
  293. pPDev - the driver's PDEV
  294. pPatRect - the DRAWPATRECT structure from the app
  295. Return Value:
  296. 1 if successful. Otherwise, 0.
  297. --*/
  298. {
  299. WORD wPattern, wStyle;
  300. RECTL rcClip;
  301. COMMAND *pCmd;
  302. ULONG ulRes = 0;
  303. if (!(pPDev->fMode & PF_RECT_FILL))
  304. return 0;
  305. wStyle = pPatRect->wStyle;
  306. if (!((wStyle+1) & 3)) // same as (wStyle < 0 || wStyle > 2)
  307. return 0; // we support only solid fill
  308. // Reset the brush, before downloading rule unless we are going to use
  309. // a white rectangle command
  310. if (wStyle != 1)
  311. GSResetBrush(pPDev);
  312. //
  313. // clip to printable region
  314. //
  315. rcClip.left = MAX(0, pPatRect->ptPosition.x);
  316. rcClip.top = MAX(0, pPatRect->ptPosition.y);
  317. rcClip.right = MIN(pPDev->szBand.cx,
  318. pPatRect->ptPosition.x + pPatRect->ptSize.x);
  319. rcClip.bottom = MIN(pPDev->szBand.cy,
  320. pPatRect->ptPosition.y + pPatRect->ptSize.y);
  321. //
  322. // check if we end up with an empty rect. If not, put down the rule.
  323. //
  324. if (rcClip.right > rcClip.left && rcClip.bottom > rcClip.top)
  325. {
  326. DWORD dwXSize,dwYSize;
  327. //
  328. // Move to the starting position. rcClip is in device units to
  329. // which we must add the offset of the band origin
  330. //
  331. XMoveTo(pPDev, rcClip.left+pPDev->rcClipRgn.left, MV_GRAPHICS);
  332. YMoveTo(pPDev, rcClip.top+pPDev->rcClipRgn.top, MV_GRAPHICS);
  333. //
  334. // The RectFill commands expect master units.
  335. //
  336. dwXSize = pPDev->dwRectXSize;
  337. pPDev->dwRectXSize = (rcClip.right - rcClip.left) * pPDev->ptGrxScale.x;
  338. dwYSize = pPDev->dwRectYSize;
  339. pPDev->dwRectYSize = (rcClip.bottom - rcClip.top) * pPDev->ptGrxScale.y;
  340. //
  341. // check whether the rectangle size is different and update if necessary
  342. //
  343. if (dwXSize != pPDev->dwRectXSize ||
  344. (!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)) &&
  345. !(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL))))
  346. {
  347. WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_SETRECTWIDTH));
  348. }
  349. if (dwYSize != pPDev->dwRectYSize ||
  350. (!(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)) &&
  351. !(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL))))
  352. {
  353. WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_SETRECTHEIGHT));
  354. }
  355. //
  356. // range-check the pattern based upon the kind of rule.
  357. //
  358. switch (wStyle)
  359. {
  360. case 0:
  361. //
  362. // black fill, which is max gray fill unless CmdRectBlackFill exists
  363. //
  364. if (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL))
  365. WriteChannel(pPDev, pCmd);
  366. else
  367. {
  368. pPDev->dwGrayPercentage = pPDev->dwMaxGrayFill;
  369. WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL));
  370. }
  371. ulRes = 1;
  372. break;
  373. case 1:
  374. //
  375. // White (erase) fill
  376. //
  377. if (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL))
  378. {
  379. WriteChannel(pPDev, pCmd);
  380. ulRes = 1;
  381. }
  382. break;
  383. case 2:
  384. //
  385. // Shaded gray fill.
  386. //
  387. // If 100% black use black rectangle fill anyway
  388. //
  389. if (pPatRect->wPattern == 100 &&
  390. (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL)))
  391. {
  392. WriteChannel(pPDev, pCmd);
  393. }
  394. // If 0% black use white rectangle fill
  395. //
  396. else if (pPatRect->wPattern == 0 &&
  397. (pCmd = COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL)))
  398. {
  399. WriteChannel(pPDev, pCmd);
  400. }
  401. //
  402. // Check for the gray range.
  403. //
  404. else
  405. {
  406. if ((wPattern = pPatRect->wPattern) < (WORD)pPDev->dwMinGrayFill)
  407. wPattern = (WORD)pPDev->dwMinGrayFill;
  408. if (wPattern > (WORD)pPDev->dwMaxGrayFill)
  409. wPattern = (WORD)pPDev->dwMaxGrayFill;
  410. pPDev->dwGrayPercentage = (DWORD)wPattern;
  411. WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL));
  412. }
  413. ulRes = 1;
  414. break;
  415. }
  416. //
  417. // update internal coordinates, if necessary. BUG_BUG, do we really need cx/cyafterfill in PDEV?
  418. //
  419. if (ulRes == 1)
  420. {
  421. if (pPDev->cxafterfill == CXARF_AT_RECT_X_END)
  422. XMoveTo(pPDev, pPatRect->ptSize.x,
  423. MV_GRAPHICS | MV_UPDATE | MV_RELATIVE);
  424. if (pPDev->cyafterfill == CYARF_AT_RECT_Y_END)
  425. YMoveTo(pPDev, pPatRect->ptSize.y,
  426. MV_GRAPHICS | MV_UPDATE | MV_RELATIVE);
  427. if (wStyle != 1)
  428. {
  429. INT i;
  430. BYTE ubMask = BGetMask(pPDev,&rcClip);
  431. for (i = rcClip.top;i < rcClip.bottom;i++)
  432. pPDev->pbScanBuf[i] |= ubMask;
  433. }
  434. }
  435. } // if (!IsRectEmpty(&rcClip))
  436. return ulRes;
  437. }