Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

461 lines
14 KiB

  1. //************************************************************************
  2. // Generic Win 3.1 fax printer driver support. 32-bit printer driver
  3. // functions. Runs in the graphics engine context (CSRSS).
  4. //
  5. // History:
  6. // 02-jan-95 nandurir created.
  7. // 01-feb-95 reedb Clean-up, support printer install and bug fixes.
  8. // 14-mar-95 reedb Use GDI hooks to move most functionality to UI.
  9. // 16-aug-95 reedb Move to kernel mode. Debug output and validate
  10. // functions moved from FAXCOMM.C.
  11. //
  12. //************************************************************************
  13. #include "wowfaxdd.h"
  14. //************************************************************************
  15. // Globals
  16. //************************************************************************
  17. DRVFN DrvFnTab[] = {
  18. {INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
  19. {INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
  20. {INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
  21. {INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
  22. {INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
  23. {INDEX_DrvStartDoc, (PFN)DrvStartDoc },
  24. {INDEX_DrvStartPage, (PFN)DrvStartPage },
  25. {INDEX_DrvSendPage, (PFN)DrvSendPage },
  26. {INDEX_DrvEndDoc, (PFN)DrvEndDoc },
  27. {INDEX_DrvDitherColor, (PFN)DrvDitherColor },
  28. {INDEX_DrvEscape, (PFN)DrvEscape},
  29. };
  30. #define NO_DRVFN (sizeof(DrvFnTab) / sizeof(DrvFnTab[0]))
  31. #if DBG
  32. //************************************************************************
  33. // faxlogprintf - Driver version of the debug output function.
  34. //
  35. //************************************************************************
  36. VOID faxlogprintf(PCHAR pszFmt, ...)
  37. {
  38. va_list ap;
  39. char buffer[256];
  40. va_start(ap, pszFmt);
  41. EngDebugPrint("", pszFmt, ap);
  42. va_end(ap);
  43. }
  44. #endif
  45. //************************************************************************
  46. // ValidateFaxDev - Validates the FAXDEV structure by checking the DWORD
  47. // signature, which is a known fixed value.
  48. //
  49. //************************************************************************
  50. BOOL ValidateFaxDev(LPFAXDEV lpFaxDev)
  51. {
  52. if (lpFaxDev) {
  53. if (lpFaxDev->id == FAXDEV_ID) {
  54. return TRUE;
  55. }
  56. LOGDEBUG(("ValidateFaxDev failed, bad id, lpFaxDev: %X\n", lpFaxDev));
  57. }
  58. else {
  59. LOGDEBUG(("ValidateFaxDev failed, lpFaxDev: NULL\n"));
  60. }
  61. return FALSE;
  62. }
  63. //************************************************************************
  64. // DllInitProc
  65. //************************************************************************
  66. BOOL DllInitProc(HMODULE hModule, DWORD Reason, PCONTEXT pContext)
  67. {
  68. UNREFERENCED_PARAMETER(hModule);
  69. UNREFERENCED_PARAMETER(Reason);
  70. UNREFERENCED_PARAMETER(pContext);
  71. return TRUE;
  72. }
  73. //***************************************************************************
  74. // DrvEnableDriver
  75. //***************************************************************************
  76. BOOL DrvEnableDriver(ULONG iEngineVersion, ULONG cb, DRVENABLEDATA *pded)
  77. {
  78. LOGDEBUG(("WOWFAX!DrvEnableDriver, iEngineVersion: %X, cb: %X, pded: %X\n", iEngineVersion, cb, pded));
  79. pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
  80. if (cb < sizeof(DRVENABLEDATA)) {
  81. LOGDEBUG(("WOWFAX!DrvEnableDriver, failed\n"));
  82. return FALSE;
  83. }
  84. pded->c = NO_DRVFN;
  85. pded->pdrvfn = DrvFnTab;
  86. return TRUE;
  87. }
  88. //***************************************************************************
  89. // DrvDisableDriver
  90. //***************************************************************************
  91. VOID DrvDisableDriver(VOID)
  92. {
  93. LOGDEBUG(("WOWFAX!DrvDisableDriver\n"));
  94. return;
  95. }
  96. //***************************************************************************
  97. // DrvEnablePDEV
  98. //***************************************************************************
  99. DHPDEV DrvEnablePDEV(DEVMODEW *pdevmode, // Driver data, Client FAXDEV
  100. PWSTR pwstrPrtName, // Printer's name in CreateDC()
  101. ULONG cPatterns, // Count of standard patterns
  102. HSURF *phsurfPatterns, // Buffer for standard patterns
  103. ULONG cjGdiInfo, // Size of buffer for GdiInfo
  104. ULONG *pulGdiInfo, // Buffer for GDIINFO
  105. ULONG cjDevInfo, // Number of bytes in devinfo
  106. DEVINFO *pdevinfo, // Device info
  107. HDEV hdev,
  108. PWSTR pwstrDeviceName, // Device Name - "LaserJet II"
  109. HANDLE hDriver // Printer handle for spooler access
  110. )
  111. {
  112. LPFAXDEV lpCliFaxDev, lpSrvFaxDev = NULL;
  113. LOGDEBUG(("WOWFAX!DrvEnablePDEV, pdevmode: %X, pwstrPrtName: %S\n", pdevmode, pwstrPrtName));
  114. if (pdevmode) {
  115. // Point to the end of the DEVMODE where the FAXDEV is located.
  116. lpCliFaxDev = (LPFAXDEV) ((PBYTE)pdevmode + pdevmode->dmSize);
  117. // Allocate a server side FAXDEV to be passed back to GDI. Copy the
  118. // client side FAXDEV to the server side FAXDEV. Note all pointers in
  119. // the client FAXDEV reference client side memory and cannot be
  120. // dereferenced on the server side.
  121. lpSrvFaxDev = (LPFAXDEV)EngAllocMem(0, sizeof(FAXDEV), FAXDEV_ID);
  122. LOGDEBUG(("WOWFAX!DrvEnablePDEV, allocated lpSrvFaxDev: %X\n", lpSrvFaxDev));
  123. if (InitPDEV(lpCliFaxDev, lpSrvFaxDev,
  124. cPatterns, phsurfPatterns,
  125. cjGdiInfo, pulGdiInfo,
  126. cjDevInfo, pdevinfo)) {
  127. lpSrvFaxDev->hDriver = hDriver;
  128. return (DHPDEV)lpSrvFaxDev;
  129. }
  130. else {
  131. LOGDEBUG(("WOWFAX!DrvEnablePDEV, failed\n"));
  132. if (lpSrvFaxDev) {
  133. EngFreeMem(lpSrvFaxDev);
  134. lpSrvFaxDev = NULL;
  135. }
  136. }
  137. }
  138. return (DHPDEV)lpSrvFaxDev;
  139. }
  140. //***************************************************************************
  141. // InitPDEV - Called by DrvEnablePDEV and DrvRestartPDEV to initialize the
  142. // server side PDEV/FAXDEV.
  143. //***************************************************************************
  144. BOOL InitPDEV(
  145. LPFAXDEV lpCliFaxDev, // Pointer to the client side FAXDEV
  146. LPFAXDEV lpSrvFaxDev, // Pointer to the server side FAXDEV
  147. ULONG cPatterns, // Count of standard patterns
  148. HSURF *phsurfPatterns, // Buffer for standard patterns
  149. ULONG cjGdiInfo, // Size of buffer for GdiInfo
  150. ULONG *pulGdiInfo, // Buffer for GDIINFO
  151. ULONG cjDevInfo, // Number of bytes in devinfo
  152. DEVINFO *pdevinfo // Device info
  153. )
  154. {
  155. PGDIINFO pgdiinfo = (PGDIINFO)pulGdiInfo;
  156. ULONG uColors[2];
  157. if (!ValidateFaxDev(lpCliFaxDev)) {
  158. return FALSE;
  159. }
  160. // lpSrvFaxDev hasn't been initialized yet, so just check pointer.
  161. if (lpSrvFaxDev == NULL) {
  162. LOGDEBUG(("WOWFAX!InitPDEV, failed, NULL lpSrvFaxDev parameter\n"));
  163. return FALSE;
  164. }
  165. // Copy client FAXDEV to server.
  166. RtlCopyMemory(lpSrvFaxDev, lpCliFaxDev, sizeof(FAXDEV));
  167. // Copy GDIINFO from client FAXDEV to the GDI buffer for GDIINFO.
  168. RtlCopyMemory(pgdiinfo, &(lpCliFaxDev->gdiinfo), sizeof(GDIINFO));
  169. // Initialize the DEVINFO structure.
  170. uColors[0] = RGB(0x00, 0x00, 0x00);
  171. uColors[1] = RGB(0xff, 0xff, 0xff);
  172. pdevinfo->hpalDefault = EngCreatePalette(PAL_INDEXED, 2, uColors, 0, 0, 0);
  173. pdevinfo->iDitherFormat = BMF_1BPP;
  174. // Make sure we don't journal.
  175. pdevinfo->flGraphicsCaps |= GCAPS_DONTJOURNAL;
  176. // Make sure we do dither.
  177. pdevinfo->flGraphicsCaps |= GCAPS_HALFTONE | GCAPS_MONO_DITHER |
  178. GCAPS_COLOR_DITHER;
  179. // Copy the DEVINFO data to the server side FAXDEV.
  180. RtlCopyMemory(&(lpSrvFaxDev->devinfo), pdevinfo, sizeof(DEVINFO));
  181. return TRUE;
  182. }
  183. //***************************************************************************
  184. // DrvCompletePDEV
  185. //***************************************************************************
  186. VOID DrvCompletePDEV(DHPDEV dhpdev, HDEV hdev)
  187. {
  188. LPFAXDEV lpSrvFaxDev = (LPFAXDEV) dhpdev;
  189. LOGDEBUG(("WOWFAX!DrvCompletePDEV, dhpdev %X\n", dhpdev));
  190. if (ValidateFaxDev(lpSrvFaxDev)) {
  191. // Store the gdi handle.
  192. lpSrvFaxDev->hdev = hdev;
  193. }
  194. else {
  195. LOGDEBUG(("WOWFAX!DrvCompletePDEV, failed\n"));
  196. }
  197. return;
  198. }
  199. //***************************************************************************
  200. // DrvDisablePDEV
  201. //***************************************************************************
  202. VOID DrvDisablePDEV(DHPDEV dhpdev)
  203. {
  204. LPFAXDEV lpSrvFaxDev = (LPFAXDEV) dhpdev;
  205. LOGDEBUG(("WOWFAX!DrvDisablePDEV, dhpdev %X\n", dhpdev));
  206. if (ValidateFaxDev(lpSrvFaxDev)) {
  207. if (lpSrvFaxDev->devinfo.hpalDefault) {
  208. EngDeletePalette(lpSrvFaxDev->devinfo.hpalDefault);
  209. }
  210. EngFreeMem(lpSrvFaxDev);
  211. LOGDEBUG(("WOWFAX!DrvDisablePDEV, deallocated lpSrvFaxDev: %X\n", lpSrvFaxDev));
  212. }
  213. else {
  214. LOGDEBUG(("WOWFAX!DrvDisablePDEV, failed\n"));
  215. }
  216. return;
  217. }
  218. //***************************************************************************
  219. // DrvEnableSurface
  220. //***************************************************************************
  221. HSURF DrvEnableSurface(DHPDEV dhpdev)
  222. {
  223. LPFAXDEV lpFaxDev = (LPFAXDEV)dhpdev;
  224. HBITMAP hbm = 0;
  225. LOGDEBUG(("WOWFAX!DrvEnableSurface, lpFaxDev: %X\n", lpFaxDev));
  226. if (ValidateFaxDev(lpFaxDev)) {
  227. // GDI will allocate space for the bitmap bits. We'll use a DrvEscape
  228. // to copy them to the client side.
  229. hbm = EngCreateBitmap(lpFaxDev->gdiinfo.szlPhysSize,
  230. lpFaxDev->bmWidthBytes,
  231. lpFaxDev->bmFormat, BMF_TOPDOWN, NULL);
  232. if (hbm) {
  233. lpFaxDev->hbm = hbm;
  234. EngAssociateSurface((HSURF)hbm, lpFaxDev->hdev, 0);
  235. return (HSURF)hbm;
  236. }
  237. LOGDEBUG(("WOWFAX!DrvEnableSurface, EngCreateBitmap failed\n"));
  238. }
  239. return (HSURF)hbm;
  240. }
  241. //***************************************************************************
  242. // DrvDisableSurface
  243. //***************************************************************************
  244. VOID DrvDisableSurface(
  245. DHPDEV dhpdev
  246. )
  247. {
  248. LPFAXDEV lpFaxDev = (LPFAXDEV)dhpdev;
  249. LOGDEBUG(("WOWFAX!DrvDisableSurface, lpFaxDev: %X\n", lpFaxDev));
  250. if (ValidateFaxDev(lpFaxDev)) {
  251. if (lpFaxDev->hbm) {
  252. EngDeleteSurface((HSURF)lpFaxDev->hbm);
  253. lpFaxDev->hbm = 0;
  254. return;
  255. }
  256. }
  257. return;
  258. }
  259. //***************************************************************************
  260. // DrvStartDoc
  261. //***************************************************************************
  262. BOOL DrvStartDoc(
  263. SURFOBJ *pso,
  264. PWSTR pwszDocName,
  265. DWORD dwJobId
  266. )
  267. {
  268. LOGDEBUG(("WOWFAX!DrvStartDoc, pso: %X, pwszDocName: %S, dwJobId: %X\n", pso, pwszDocName, dwJobId));
  269. return TRUE;
  270. }
  271. //***************************************************************************
  272. // DrvStartPage
  273. //***************************************************************************
  274. BOOL DrvStartPage(
  275. SURFOBJ *pso
  276. )
  277. {
  278. LPFAXDEV lpFaxDev = (LPFAXDEV)pso->dhpdev;
  279. BITMAP bm;
  280. RECTL rc;
  281. LOGDEBUG(("WOWFAX!DrvStartPage, pso: %X\n", pso));
  282. // Calculate the size of the rectangle based on the input data
  283. // in 'pso' - this will ensure that the entire bitmap is erased.
  284. if (ValidateFaxDev(lpFaxDev)) {
  285. rc.left = 0;
  286. rc.top = 0;
  287. rc.right = pso->lDelta * lpFaxDev->cPixPerByte;
  288. rc.bottom = pso->cjBits / pso->lDelta;
  289. EngEraseSurface(pso, &rc, COLOR_INDEX_WHITE);
  290. return TRUE;
  291. }
  292. return FALSE;
  293. }
  294. //***************************************************************************
  295. // DrvSendPage
  296. //***************************************************************************
  297. BOOL DrvSendPage(SURFOBJ *pso)
  298. {
  299. LOGDEBUG(("WOWFAX!DrvSendPage, pso %X\n", pso));
  300. return TRUE;
  301. }
  302. //***************************************************************************
  303. // DrvEndDoc
  304. //***************************************************************************
  305. BOOL DrvEndDoc(SURFOBJ *pso, FLONG fl)
  306. {
  307. LOGDEBUG(("WOWFAX!DrvEndDoc, pso %X\n", pso));
  308. return TRUE;
  309. }
  310. ULONG
  311. DrvDitherColor(
  312. DHPDEV dhpdev,
  313. ULONG iMode,
  314. ULONG rgbColor,
  315. ULONG *pulDither
  316. )
  317. {
  318. return DCR_HALFTONE;
  319. }
  320. //***************************************************************************
  321. // DrvEscape - Allows client side to get server side data.
  322. //***************************************************************************
  323. ULONG DrvEscape(
  324. SURFOBJ *pso,
  325. ULONG iEsc,
  326. ULONG cjIn,
  327. PVOID *pvIn,
  328. ULONG cjOut,
  329. PVOID *pvOut
  330. )
  331. {
  332. LPFAXDEV lpSrvFaxDev;
  333. ULONG ulRet = 0;
  334. LOGDEBUG(("WOWFAX!DrvEscape, pso %X, iEsc: %X\n", pso, iEsc));
  335. if (pso) {
  336. lpSrvFaxDev = (LPFAXDEV)pso->dhpdev;
  337. if (ValidateFaxDev(lpSrvFaxDev)) {
  338. LOGDEBUG(("WOWFAX!DrvEscape, lpSrvFaxDev: %X\n", lpSrvFaxDev));
  339. switch (iEsc) {
  340. case DRV_ESC_GET_DEVMODE_PTR:
  341. return (ULONG) lpSrvFaxDev->pdevmode;
  342. case DRV_ESC_GET_FAXDEV_PTR:
  343. return (ULONG) lpSrvFaxDev->lpClient;
  344. case DRV_ESC_GET_SURF_INFO:
  345. if (pvOut) {
  346. if (cjOut == sizeof(LONG)) {
  347. (LONG) *pvOut = pso->lDelta;
  348. return (ULONG) pso->cjBits;
  349. }
  350. }
  351. break;
  352. case DRV_ESC_GET_BITMAP_BITS:
  353. // Validate the buffer pointer and copy the bits.
  354. if (pvOut) {
  355. if (cjOut == pso->cjBits) {
  356. RtlCopyMemory(pvOut, pso->pvBits, cjOut);
  357. return cjOut;
  358. }
  359. LOGDEBUG(("WOWFAX!DrvEscape, bitmap size mismatch cjIn: %X, pso->cjBits: %X\n", cjIn, pso->cjBits));
  360. }
  361. break;
  362. // default:
  363. LOGDEBUG(("WOWFAX!DrvEscape, unknown escape: %X\n", iEsc));
  364. } //switch
  365. }
  366. }
  367. LOGDEBUG(("WOWFAX!DrvEscape, failed\n"));
  368. return ulRet;
  369. }