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.

1753 lines
43 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. enable.c
  5. Abstract:
  6. This module contains the Plotter driver's Enable and Disable functions
  7. and related routines.
  8. The functions dealing with driver initialization are as follows:
  9. DrvEnableDriver()
  10. DrvEnablePDEV()
  11. DrvResetPDEV()
  12. DrvCompletePDEV()
  13. DrvEnableSurface()
  14. DrvDisableSurface()
  15. DrvDisablePDEV()
  16. DrvDisableDriver()
  17. Author:
  18. 12-Nov-1993 Fri 10:16:36 updated
  19. Move all #define related only to this function to here
  20. 15-Nov-1993 Mon 19:31:34 updated
  21. clean up / debugging information
  22. 05-Jan-1994 Wed 22:50:28 updated
  23. Move ColorMap's RGB pen color to local so that we only need array
  24. reference, it defined PenRGBColor as DWORD from RGB() macro
  25. [Environment:]
  26. GDI Device Driver - Plotter.
  27. [Notes:]
  28. Revision History:
  29. --*/
  30. #include "precomp.h"
  31. #pragma hdrstop
  32. #define DBG_PLOTFILENAME DbgEnable
  33. #define DBG_ENABLEDRV 0x00000001
  34. #define DBG_DISABLEDRV 0x00000002
  35. #define DBG_ENABLEPDEV 0x00000004
  36. #define DBG_COMPLETEPDEV 0x00000008
  37. #define DBG_DISABLEPDEV 0x00000010
  38. #define DBG_ENABLESURF 0x00000020
  39. #define DBG_DISABLESURF 0x00000040
  40. #define DBG_GDICAPS 0x00000080
  41. #define DBG_DEVCAPS 0x00000100
  42. #define DBG_PENPAL 0x00000200
  43. #define DBG_BAND 0x00000400
  44. #define DBG_DLLINIT 0x00000800
  45. DEFINE_DBGVAR(0);
  46. #if DBG
  47. TCHAR DebugDLLName[] = TEXT("PLOTTER");
  48. #endif
  49. #define FIXUP_PLOTGPC_PDATA(pd,ps,v) \
  50. if (ps->v) {pd->v=(LPVOID)((LPBYTE)pd+((LPBYTE)(ps->v)-(LPBYTE)ps));}
  51. //
  52. // Local funtion prototypes.
  53. //
  54. BOOL
  55. CommonStartPDEV(
  56. PDEV *pPDev,
  57. DEVMODEW *pPlotDMIn,
  58. ULONG cPatterns,
  59. HSURF *phsurfPatterns,
  60. ULONG cjDevCaps,
  61. ULONG *pDevCaps,
  62. ULONG cjDevInfo,
  63. DEVINFO *pDevInfo
  64. );
  65. //
  66. // Define the table with the hooked function pointers. This table is passed
  67. // back to the NT graphic engine at DrvEnableDriver time. From then on GDI
  68. // will call our driver via these supplied hook procs.
  69. //
  70. static const DRVFN DrvFuncTable[] = {
  71. { INDEX_DrvDisableDriver, (PFN)DrvDisableDriver },
  72. { INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
  73. { INDEX_DrvResetPDEV, (PFN)DrvResetPDEV },
  74. { INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
  75. { INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
  76. { INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
  77. { INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
  78. // { INDEX_DrvQueryFont, (PFN)DrvQueryFont },
  79. // { INDEX_DrvQueryFontTree, (PFN)DrvQueryFontTree },
  80. // { INDEX_DrvQueryFontData, (PFN)DrvQueryFontData },
  81. { INDEX_DrvStrokePath, (PFN)DrvStrokePath },
  82. { INDEX_DrvStrokeAndFillPath, (PFN)DrvStrokeAndFillPath },
  83. { INDEX_DrvFillPath, (PFN)DrvFillPath },
  84. { INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush },
  85. { INDEX_DrvBitBlt, (PFN)DrvBitBlt },
  86. { INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
  87. { INDEX_DrvCopyBits, (PFN)DrvCopyBits },
  88. { INDEX_DrvPaint, (PFN)DrvPaint },
  89. { INDEX_DrvGetGlyphMode, (PFN)DrvGetGlyphMode },
  90. { INDEX_DrvTextOut, (PFN)DrvTextOut },
  91. { INDEX_DrvSendPage, (PFN)DrvSendPage },
  92. { INDEX_DrvStartPage, (PFN)DrvStartPage },
  93. { INDEX_DrvStartDoc, (PFN)DrvStartDoc },
  94. { INDEX_DrvEndDoc, (PFN)DrvEndDoc },
  95. { INDEX_DrvEscape, (PFN)DrvEscape },
  96. };
  97. #define TOTAL_DRVFUNC (sizeof(DrvFuncTable)/sizeof(DrvFuncTable[0]))
  98. #ifdef USERMODE_DRIVER
  99. HINSTANCE ghInstance;
  100. BOOL
  101. DllMain(
  102. HANDLE hModule,
  103. ULONG ulReason,
  104. PCONTEXT pContext
  105. )
  106. /*++
  107. Routine Description:
  108. DLL initialization procedure.
  109. Arguments:
  110. hModule - DLL instance handle
  111. ulReason - Reason for the call
  112. pContext - Pointer to context (not used by us)
  113. Return Value:
  114. TRUE if DLL is initialized successfully, FALSE otherwise.
  115. --*/
  116. {
  117. switch (ulReason)
  118. {
  119. case DLL_PROCESS_ATTACH:
  120. ghInstance = hModule;
  121. break;
  122. case DLL_PROCESS_DETACH:
  123. break;
  124. }
  125. return TRUE;
  126. }
  127. BOOL
  128. DrvQueryDriverInfo(
  129. DWORD dwMode,
  130. PVOID pBuffer,
  131. DWORD cbBuf,
  132. PDWORD pcbNeeded
  133. )
  134. /*++
  135. Routine Description:
  136. Query driver information
  137. Arguments:
  138. dwMode - Specify the information being queried
  139. pBuffer - Points to output buffer
  140. cbBuf - Size of output buffer in bytes
  141. pcbNeeded - Return the expected size of output buffer
  142. Return Value:
  143. TRUE if successful, FALSE if there is an error
  144. --*/
  145. {
  146. switch (dwMode)
  147. {
  148. case DRVQUERY_USERMODE:
  149. PLOTASSERT(1, "DrvQueryDriverInfo: pcbNeeded [%08lx] is NULL", pcbNeeded != NULL, pcbNeeded);
  150. *pcbNeeded = sizeof(DWORD);
  151. if (pBuffer == NULL || cbBuf < sizeof(DWORD))
  152. {
  153. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  154. return FALSE;
  155. }
  156. *((PDWORD) pBuffer) = TRUE;
  157. return TRUE;
  158. default:
  159. PLOTERR(("Unknown dwMode in DrvQueryDriverInfo: %d\n", dwMode));
  160. SetLastError(ERROR_INVALID_PARAMETER);
  161. return FALSE;
  162. }
  163. }
  164. #endif // USERMODE_DRIVER
  165. BOOL
  166. DrvEnableDriver(
  167. ULONG iEngineVersion,
  168. ULONG cb,
  169. DRVENABLEDATA *pded
  170. )
  171. /*++
  172. Routine Description:
  173. Requests the driver to fill in a structure containing recognized functions
  174. and other control information. One time initialization, such as semaphore
  175. allocation may be performed, but no device activity should happen. That
  176. is done when DrvEnablePDEV is called. This function is the only way the
  177. engine can determine what functions we supply to it.
  178. Arguments:
  179. iEngineVersion - The engine version which we run under
  180. cb - total bytes in pded
  181. pded - Pointer to the DRVENABLEDATA data structure
  182. Return Value:
  183. TRUE if sucssfully FALSE otherwise
  184. Author:
  185. 01-Dec-1993 Wed 02:03:20 created
  186. 03-Mar-1994 Thu 10:04:30 updated
  187. Adding EngineVersion check to make sure ourself can run correctly.
  188. Revision History:
  189. --*/
  190. {
  191. PLOTDBG(DBG_ENABLEDRV, ("DrvEnableDriver: EngineVersion=%08lx, Request=%08lx",
  192. iEngineVersion, DDI_DRIVER_VERSION_NT4));
  193. //
  194. // Verify the Engine version is at least what we know we can work with.
  195. // If its older, error out now, as we don't know what may happen.
  196. //
  197. if (iEngineVersion < DDI_DRIVER_VERSION_NT4) {
  198. PLOTRIP(("DrvEnableDriver: EARLIER VERSION: EngineVersion(%08lx) < Request(%08lx)",
  199. iEngineVersion, DDI_DRIVER_VERSION_NT4));
  200. SetLastError(ERROR_BAD_DRIVER_LEVEL);
  201. return(FALSE);
  202. }
  203. //
  204. // cb is a count of the number of bytes available in pded. It is not
  205. // clear that there is any significant use of the engine version number.
  206. // Returns TRUE if successfully enabled, otherwise FALSE.
  207. //
  208. // iEngineVersion is the engine version while DDI_DRIVER_VERSION is the
  209. // driver version. So, unless we re-compile the driver and get a new
  210. // version of driver, we can only stick with our version.
  211. //
  212. if (cb < sizeof(DRVENABLEDATA)) {
  213. SetLastError(ERROR_INVALID_PARAMETER);
  214. PLOTRIP(("DrvEnableDriver: cb=%ld, should be %ld\n",
  215. cb, sizeof(DRVENABLEDATA)));
  216. return(FALSE);
  217. }
  218. pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
  219. //
  220. // Fill in the driver table returned to the engine. This table is used
  221. // by GDI to call the rest of our functinos.
  222. //
  223. pded->c = TOTAL_DRVFUNC;
  224. pded->pdrvfn = (DRVFN *)DrvFuncTable;
  225. //
  226. // Initialize the GPC cache
  227. //
  228. InitCachedData();
  229. return(TRUE);
  230. }
  231. VOID
  232. DrvDisableDriver(
  233. VOID
  234. )
  235. /*++
  236. Routine Description:
  237. Called just before the engine unloads the driver. Main purpose is
  238. to allow freeing of any resources obtained during the DrvEnableDriver()
  239. call.
  240. Arguments:
  241. NONE
  242. Return Value:
  243. VOID
  244. Author:
  245. 01-Dec-1993 Wed 02:02:18 created
  246. 01-Feb-1994 Tue 22:03:03 updated
  247. Make sure we unload the cache.
  248. Revision History:
  249. --*/
  250. {
  251. DestroyCachedData();
  252. PLOTDBG(DBG_DISABLEDRV, ("DrvDisableDriver: Done!!"));
  253. }
  254. VOID
  255. FreeAllocMem(
  256. PPDEV pPDev
  257. )
  258. /*++
  259. Routine Description:
  260. This function frees all the memory allocated during the lifetime of the
  261. PDEV.
  262. Arguments:
  263. pPDev - Our instance data
  264. Return Value:
  265. VOID
  266. Author:
  267. 24-Oct-1995 Tue 16:28:35 created
  268. Revision History:
  269. --*/
  270. {
  271. //
  272. // Free any memory allocated during PDEV initialization.
  273. //
  274. if (pPDev) {
  275. PDRVHTINFO pDrvHTInfo;
  276. if (pPDev->hPalDefault) {
  277. EngDeletePalette(pPDev->hPalDefault);
  278. pPDev->hPalDefault = NULL;
  279. }
  280. if (pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData)) {
  281. if (pDrvHTInfo->pHTXB) {
  282. LocalFree((HLOCAL)pDrvHTInfo->pHTXB);
  283. pDrvHTInfo->pHTXB = NULL;
  284. }
  285. pPDev->pvDrvHTData = NULL;
  286. }
  287. if (pPDev->pPenCache) {
  288. LocalFree((HLOCAL)pPDev->pPenCache);
  289. pPDev->pPenCache = NULL;
  290. }
  291. if (pPDev->pTransPosTable) {
  292. LocalFree((HLOCAL)pPDev->pTransPosTable);
  293. pPDev->pTransPosTable = NULL;
  294. }
  295. FreeOutBuffer(pPDev);
  296. LocalFree((HLOCAL)pPDev);
  297. }
  298. }
  299. DHPDEV
  300. DrvEnablePDEV(
  301. DEVMODEW *pPlotDMIn,
  302. PWSTR pwszLogAddr,
  303. ULONG cPatterns,
  304. HSURF *phsurfPatterns,
  305. ULONG cjDevCaps,
  306. ULONG *pDevCaps,
  307. ULONG cjDevInfo,
  308. DEVINFO *pDevInfo,
  309. HDEV hdev,
  310. PWSTR pwszDeviceName,
  311. HANDLE hDriver
  312. )
  313. /*++
  314. Routine Description:
  315. Function called to let the driver create the data structures
  316. needed to support the device, and also to tell the engine
  317. about its capabilities. This is the stage where we find out
  318. exactly which device we are dealing with, and so we need to
  319. find out its capabilities.
  320. Arguments:
  321. pPlotDMIn - Pointer to the DEVMODE data structure
  322. pwszLogAddr - pointer to the output location, (ie. LPT1
  323. cPatterns - Count of pattern to be set in phsurfPatterns
  324. phsurfPatterns - pointer to the standard pattern HSURF array
  325. cjDevCaps - total size of pDevCaps pointed to.
  326. pDevCaps - pointer to the device cap DWORDs
  327. cjDevInfo - total size of pDevInfo pointed to
  328. pDevInfo - pointer to the DEVINFO data structure
  329. hdev - Handle to the logical device from the engine
  330. pwszDeviceName - pointer to the plotter device name
  331. hDriver - handle to this driver
  332. Return Value:
  333. DHPDEV if sucessful, NULL if failed
  334. Author:
  335. 15-Dec-1993 Wed 21:04:40 updated
  336. Add cached mechanism for the PLOTGPC
  337. 14-Dec-1993 Tue 20:22:26 updated
  338. Update how the pen plotter data should work
  339. 23-Nov-1993 Tue 19:48:08 updated
  340. Clean up and using new devmode.c in ..\lib directory
  341. 17:30 on Mon 1 Apr 1991
  342. Took skeletal code from RASDD printer driver
  343. 16-Jul-1996 Tue 13:59:15 updated
  344. Fix up the pData in the PLOTGPC/GPCVARSIZE structure, since the
  345. pointer is based on the cached GPC not the clone copy of it
  346. Revision History:
  347. --*/
  348. {
  349. PPDEV pPDev = NULL;
  350. PPLOTGPC pPlotGPC;
  351. LPWSTR pwszDataFile = NULL;
  352. #ifdef USERMODE_DRIVER
  353. PDRIVER_INFO_2 pDriverInfo = NULL;
  354. DWORD dwBytesNeeded;
  355. #endif
  356. UNREFERENCED_PARAMETER(pwszLogAddr);
  357. #ifndef USERMODE_DRIVER
  358. pwszDataFile = EngGetPrinterDataFileName(hdev);
  359. #else
  360. if (!GetPrinterDriver(hDriver, NULL, 2, NULL, 0, &dwBytesNeeded) &&
  361. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  362. (pDriverInfo = (PDRIVER_INFO_2)LocalAlloc(LPTR, dwBytesNeeded)) &&
  363. GetPrinterDriver(hDriver, NULL, 2, (LPBYTE)pDriverInfo, dwBytesNeeded, &dwBytesNeeded))
  364. {
  365. pwszDataFile = pDriverInfo->pDataFile;
  366. }
  367. #endif // !USERMODE_DRIVER
  368. if (!pwszDataFile) {
  369. PLOTRIP(("DrvEnablePDEV: pwszDataFile is NULL"));
  370. } else if (!(pPlotGPC = GetCachedPlotGPC(pwszDataFile))) {
  371. PLOTRIP(("DrvEnablePDEV: GetCachedPlotGPC(%ws) failed", pwszDataFile));
  372. } else if (!(pPDev = (PPDEV)LocalAlloc(LPTR,
  373. sizeof(PDEV) + sizeof(DRVHTINFO) +
  374. pPlotGPC->cjThis +
  375. pPlotGPC->SizeExtra))) {
  376. //
  377. // Free the cached pPlotGPC before we leave
  378. //
  379. UnGetCachedPlotGPC(pPlotGPC);
  380. PLOTRIP(("DrvEnablePDEV: LocalAlloc(PDEV + DRVHTINFO + pPlotGPC) failed."));
  381. } else {
  382. PLOTDBG(DBG_ENABLEPDEV,("EnablePDEV: PlotGPC data file=%ws",
  383. pwszDataFile));
  384. //
  385. // If we got the PDEV set the ID for later checking, also set the
  386. // hPrinter so we can use it later
  387. //
  388. pPDev->pvDrvHTData = (LPVOID)((LPBYTE)pPDev + sizeof(PDEV));
  389. pPDev->hPrinter = hDriver;
  390. pPDev->SizePDEV = sizeof(PDEV);
  391. pPDev->PDEVBegID = PDEV_BEG_ID;
  392. pPDev->PDEVEndID = PDEV_END_ID;
  393. //
  394. // We will get the PLOTGPC from the cach, the pPlotGPC is
  395. // allocated by the ReadPlotGPCFromFile() using LocalAlloc().
  396. //
  397. // *** NOW we will Clone the cached pPlotGPC then un-cached it
  398. //
  399. pPDev->pPlotGPC = (PPLOTGPC)((LPBYTE)pPDev + sizeof (PDEV) +
  400. sizeof(DRVHTINFO));
  401. CopyMemory(pPDev->pPlotGPC,
  402. pPlotGPC,
  403. pPlotGPC->cjThis + pPlotGPC->SizeExtra);
  404. //
  405. // 16-Jul-1996 Tue 13:59:15 updated
  406. // Fix up the pData in the PLOTGPC/GPCVARSIZE structure, since the
  407. // pointer is based on the cached GPC not the clone copy of it
  408. //
  409. FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, InitString.pData);
  410. FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, Forms.pData);
  411. FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, Pens.pData);
  412. UnGetCachedPlotGPC(pPlotGPC);
  413. //
  414. // Now, depending on if its a pen/raster device, we will update
  415. // the pen data.
  416. //
  417. PLOTASSERT(1, "Raster Plotter should not have PEN data [%08lx]",
  418. ((pPDev->pPlotGPC->Flags & PLOTF_RASTER) &&
  419. (pPDev->pPlotGPC->Pens.pData == NULL)) ||
  420. ((!(pPDev->pPlotGPC->Flags & PLOTF_RASTER)) &&
  421. (pPDev->pPlotGPC->Pens.pData != NULL)),
  422. pPDev->pPlotGPC->Pens.pData);
  423. //
  424. // Read the data from the registry which defines device settings.
  425. // The user may have modified the paper type loaded etc.
  426. //
  427. GetDefaultPlotterForm(pPDev->pPlotGPC, &(pPDev->CurPaper));
  428. //
  429. // Set the default Flags in case we did not update from the registry
  430. //
  431. pPDev->PPData.Flags = PPF_AUTO_ROTATE |
  432. PPF_SMALLER_FORM |
  433. PPF_MANUAL_FEED_CX;
  434. if (IS_RASTER(pPDev)) {
  435. //
  436. // Raster devices do not need pen data
  437. //
  438. UpdateFromRegistry(hDriver,
  439. &(pPDev->pPlotGPC->ci),
  440. &(pPDev->pPlotGPC->DevicePelsDPI),
  441. &(pPDev->pPlotGPC->HTPatternSize),
  442. &(pPDev->CurPaper),
  443. &(pPDev->PPData),
  444. NULL,
  445. 0,
  446. NULL);
  447. } else {
  448. //
  449. // The Pen plotter does not need ColorInfo, DevicePelsDPI and
  450. // HTPatternSize
  451. //
  452. UpdateFromRegistry(hDriver,
  453. NULL,
  454. NULL,
  455. NULL,
  456. &(pPDev->CurPaper),
  457. &(pPDev->PPData),
  458. NULL,
  459. MAKELONG(0xFFFF, pPDev->pPlotGPC->MaxPens),
  460. (PPENDATA)pPDev->pPlotGPC->Pens.pData);
  461. }
  462. //
  463. // common code for DrvEnablePDEV and DrvResetPDEV
  464. // we must first copy the device name to the pPDev->PlotDM
  465. // then call the common code.
  466. //
  467. WCPYFIELDNAME(pPDev->PlotDM.dm.dmDeviceName, pwszDeviceName);
  468. if (!CommonStartPDEV(pPDev,
  469. pPlotDMIn,
  470. cPatterns,
  471. phsurfPatterns,
  472. cjDevCaps,
  473. pDevCaps,
  474. cjDevInfo,
  475. pDevInfo)) {
  476. FreeAllocMem(pPDev);
  477. pPDev = NULL;
  478. }
  479. }
  480. #ifdef USERMODE_DRIVER
  481. if (pDriverInfo) {
  482. LocalFree((HLOCAL)pDriverInfo);
  483. }
  484. #endif // USERMODE_DRIVER
  485. return((DHPDEV)pPDev);
  486. }
  487. BOOL
  488. DrvResetPDEV(
  489. DHPDEV dhpdevOld,
  490. DHPDEV dhpdevNew
  491. )
  492. /*++
  493. Routine Description:
  494. Called when an application wishes to change the output style in the
  495. midst of a job. Typically this would be to change from portrait to
  496. landscape or vice versa. Any other sensible change is permitted.
  497. Arguments:
  498. dhpdevOld - the OLD pPDev which we returned in DrvEnablePDEV
  499. dhpdevNew - the NEW pPDev which we returned in DrvEnablePDEV
  500. Return Value:
  501. BOOLEAN
  502. Author:
  503. 23-Nov-1993 Tue 20:07:45 updated
  504. totaly re-write
  505. 17:30 on Mon 1 Apr 1991
  506. Took skeletal code from RASDD printer driver
  507. Revision History:
  508. --*/
  509. {
  510. #define pPDevOld ((PDEV *) dhpdevOld)
  511. #define pPDevNew ((PDEV *) dhpdevNew)
  512. //
  513. // Make sure we got the correct pPlotDMin for this pPDev
  514. //
  515. if ((pPDevOld->PlotDM.dm.dmDriverVersion !=
  516. pPDevNew->PlotDM.dm.dmDriverVersion) ||
  517. (wcscmp((LPWSTR)pPDevOld->PlotDM.dm.dmDeviceName,
  518. (LPWSTR)pPDevNew->PlotDM.dm.dmDeviceName))) {
  519. PLOTERR(("DrvResetPDEV: Incompatible PLOTDEVMODE"));
  520. SetLastError(ERROR_INVALID_PARAMETER);
  521. return(FALSE);
  522. }
  523. //
  524. // We have nothing to carry over from old to new
  525. //
  526. return(TRUE);
  527. #undef pPDevNew
  528. #undef pPDevOld
  529. }
  530. VOID
  531. DrvCompletePDEV(
  532. DHPDEV dhpdev,
  533. HDEV hpdev
  534. )
  535. /*++
  536. Routine Description:
  537. Called when the engine has completed installation of the physical
  538. device. Basically it provides the connection between the
  539. engine's hpdev and ours. Some functions require us to pass in
  540. the engines's hpdev, so we save it now in our pdev so that we
  541. can get to it later.
  542. Arguments:
  543. dhpdev - Returned from dhpdevCreatePDEV
  544. hpdev - Engine's corresponding handle
  545. Return Value:
  546. VOID
  547. Author:
  548. 01-Dec-1993 Wed 01:56:58 created
  549. Revision History:
  550. --*/
  551. {
  552. //
  553. // Simply record the value in the PDEV we have allocated.
  554. //
  555. ((PPDEV)dhpdev)->hpdev = hpdev;
  556. PLOTDBG(DBG_COMPLETEPDEV, ("CompletePDEV: Done!"));
  557. }
  558. VOID
  559. DrvDisablePDEV(
  560. DHPDEV dhpdev
  561. )
  562. /*++
  563. Routine Description:
  564. Called when the engine has finished with this PDEV. Basically we throw
  565. away all connections etc. then free the memory.
  566. Arguments:
  567. dhpdev - OUR handle to the pdev
  568. Return Value:
  569. VOID
  570. Author:
  571. 01-Dec-1993 Wed 01:55:43 created
  572. Revision History:
  573. --*/
  574. {
  575. #define pPDev ((PDEV *) dhpdev)
  576. //
  577. // Undo all that has been done with the PDEV. Basically this means
  578. // freeing the memory we consumed.
  579. //
  580. FreeAllocMem(pPDev);
  581. PLOTDBG(DBG_DISABLEPDEV, ("DrvDisablePDEV: FreeAllocMem() completes"));
  582. #undef pPDev
  583. }
  584. HSURF
  585. DrvEnableSurface(
  586. DHPDEV dhpdev
  587. )
  588. /*++
  589. Routine Description:
  590. Function to create the physical drawing surface for the pdev
  591. that was created earlier. Since we don't really have a bitmap surface,
  592. all we do here is allocate the output buffer. This is typical for a
  593. Device Managed Surface. After this call completes succesfully, GDI can
  594. start drawing on our surface.
  595. Arguments:
  596. dhpdev - OUR handle to the pdev
  597. Return Value:
  598. HSURF for the surface we created
  599. Author:
  600. 01-Dec-1993 Wed 01:47:36 created
  601. 10-Dec-1993 Fri 16:36:37 updated
  602. Move PlotCreatePalette() to here to prevent GP
  603. 16-Dec-1993 Thu 12:16:11 updated
  604. Move PlotCreatePalette() out to SendPageHeader() in output.c so that
  605. we do not sending some PC commands which has no effects.
  606. 06-Jan-1994 Thu 04:12:37 updated
  607. Re-arrange the code sequence.
  608. Adding Error codes so it will failed the call if engine said so.
  609. Revision History:
  610. --*/
  611. {
  612. #define pPDev ((PPDEV)dhpdev)
  613. PDRVHTINFO pDrvHTInfo;
  614. SIZEL SurfSize;
  615. pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData);
  616. //
  617. // Make sure we delete this xlate table before we process the new
  618. // surface
  619. //
  620. if (pDrvHTInfo->pHTXB) {
  621. LocalFree((HLOCAL)pDrvHTInfo->pHTXB);
  622. pDrvHTInfo->pHTXB = NULL;
  623. }
  624. pDrvHTInfo->Flags = 0;
  625. pDrvHTInfo->PalXlate[0] = 0xff;
  626. pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
  627. //
  628. // Since output is expected to follow this call, allocate storage for the
  629. // output buffer. This used to be statically allocated within the PDEV but
  630. // now we can save that space for INFO type DCs, since CreateIC won't
  631. // actually end up calling DrvEnableSurface.
  632. //
  633. if (!AllocOutBuffer(pPDev)) {
  634. PLOTERR(("DrvEnableSurface: AllocOutBuffer() failed"));
  635. return(NULL);
  636. }
  637. //
  638. // For now pass in my PDev pointer as the dhsurf value. If we actually
  639. // need to pass back an hsurf to the engine later, We can use this value
  640. // as a pointer to the hsurf value stored in our PDev.
  641. //
  642. SurfSize.cx = pPDev->HorzRes;
  643. SurfSize.cy = pPDev->VertRes;
  644. if (!(pPDev->hsurf = EngCreateDeviceSurface((DHSURF)pPDev, SurfSize,
  645. IS_RASTER(pPDev) ? BMF_24BPP : BMF_4BPP))) {
  646. PLOTERR(("DrvEnableSurface: EngCreateDeviceSurface() failed"));
  647. return(NULL);
  648. }
  649. //
  650. //
  651. // Now we need to associate the newly created surface with the already
  652. // created PDEV. In this function, we inform the NT graphics engine,
  653. // which functions our driver supports.
  654. //
  655. if (!EngAssociateSurface(pPDev->hsurf,
  656. (HDEV)pPDev->hpdev,
  657. HOOK_BITBLT |
  658. HOOK_STRETCHBLT |
  659. HOOK_COPYBITS |
  660. HOOK_STROKEPATH |
  661. HOOK_FILLPATH |
  662. HOOK_STROKEANDFILLPATH |
  663. HOOK_PAINT |
  664. HOOK_TEXTOUT)) {
  665. PLOTERR(("DrvEnableSurface: EngAssociateSurface() failed"));
  666. DrvDisableSurface((DHPDEV)pPDev->hpdev);
  667. EngDeleteSurface(pPDev->hsurf);
  668. return(NULL);
  669. }
  670. return(pPDev->hsurf);
  671. #undef pPDev
  672. }
  673. VOID
  674. DrvDisableSurface(
  675. DHPDEV dhpdev
  676. )
  677. /*++
  678. Routine Description:
  679. The drawing surface is no longer required, so we can delete any
  680. memory we allocated in conjunction with it.
  681. Arguments:
  682. dhpdev - our pPDev
  683. Return Value:
  684. VOID
  685. Author:
  686. 01-Dec-1993 Wed 01:45:39 created
  687. Revision History:
  688. --*/
  689. {
  690. #define pPDev ((PPDEV)dhpdev)
  691. if (pPDev->hsurf) {
  692. EngDeleteSurface(pPDev->hsurf);
  693. }
  694. #undef pPDev
  695. }
  696. DWORD
  697. hypot(
  698. DWORD x,
  699. DWORD y
  700. )
  701. /*++
  702. Routine Description:
  703. Returns the length of the hypotenous of a xRight triangle whose sides
  704. are passed in as the parameters.
  705. Arguments:
  706. x - x side of the triangle
  707. y - y size of the triangle
  708. Return Value:
  709. hypotenous
  710. Author:
  711. 13:54 on Tue 02 Feb 1993
  712. Re-instated from Win 3.1, for compatability.
  713. 01-Dec-1993 Wed 01:10:55 updated
  714. update to DWORD
  715. Revision History:
  716. --*/
  717. {
  718. DWORD hypo;
  719. DWORD Delta;
  720. DWORD Target;
  721. //
  722. // Finds the hypoteneous of a xRight triangle with legs equal to x and y.
  723. // Assumes x, y, hypo are integers. Use sq(x) + sq(y) = sq(hypo);
  724. // Start with MAX(x, y), use sq(x + 1) = sq(x) + 2x + 1 to incrementally
  725. // get to the target hypotenouse.
  726. //
  727. hypo = max(x, y);
  728. Target = min(x, y);
  729. Target *= Target;
  730. for (Delta = 0; Delta < Target; hypo++) {
  731. Delta += (DWORD)((hypo << 1) + 1);
  732. }
  733. return(hypo);
  734. }
  735. VOID
  736. FillDeviceCaps(
  737. PPDEV pPDev,
  738. GDIINFO *pGDIInfo
  739. )
  740. /*++
  741. Routine Description:
  742. Set up the device caps for this particular plotter. Some fields require
  743. calculations based on device resolution, etc.
  744. We simply fill the GDIINFO structure passed to us. The calling
  745. function will take care of copying the information into the
  746. Graphics Engine's buffer.
  747. Arguments:
  748. pPDev - Pointer to the PDEV data structure
  749. pGDIInfo - Pointer to the GDIINFO data structure to be filled in
  750. Return Value:
  751. VOID
  752. Author:
  753. 24-Nov-1993 Wed 22:38:10 updated
  754. Re-write, and using CurForm to replace the pform and PAPER_DIM
  755. 23-Dec-1993 Thu 21:56:20 updated
  756. Make halftone bitmap surface also look at dmColor which set by the
  757. user if it want to print grey scale or device is not color
  758. 07-Feb-1994 Mon 20:37:13 updated
  759. When is DMCOLOR_COLOR the ulNumColors return to the engine will be
  760. MaxPens which specified in the PCD file not 8
  761. Revision History:
  762. --*/
  763. {
  764. PDRVHTINFO pDrvHTInfo;
  765. LONG Scale;
  766. //
  767. // we will always start from clean state
  768. //
  769. ZeroMemory(pGDIInfo, sizeof(GDIINFO));
  770. //
  771. // Get pDrvHTInfo data pointer and set the basic version information
  772. //
  773. pDrvHTInfo = (PDRVHTINFO)pPDev->pvDrvHTData;
  774. pGDIInfo->ulVersion = DRIVER_VERSION;
  775. pGDIInfo->ulTechnology = (IS_RASTER(pPDev) ? DT_RASPRINTER : DT_PLOTTER);
  776. //
  777. // We have pPDev->PlotForm updated during the ValidateSetPLOTDM() call, so
  778. // use it, we need to look into the dmScale to see if we need to scale
  779. // all of the values.
  780. //
  781. Scale = (LONG)pPDev->PlotDM.dm.dmScale;
  782. pGDIInfo->ulHorzSize = pPDev->PlotForm.LogExt.cx / (Scale * 10);
  783. pGDIInfo->ulVertSize = pPDev->PlotForm.LogExt.cy / (Scale * 10);
  784. pPDev->HorzRes =
  785. pGDIInfo->ulHorzRes = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cx);
  786. pPDev->VertRes =
  787. pGDIInfo->ulVertRes = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cy);
  788. PLOTDBG(DBG_GDICAPS, ("GDICAPS: H/V Size=%d x %d, H/V Res=%ld x %ld",
  789. pGDIInfo->ulHorzSize, pGDIInfo->ulVertSize,
  790. pGDIInfo->ulHorzRes, pGDIInfo->ulVertRes));
  791. pGDIInfo->szlPhysSize.cx = SPLTOENGUNITS(pPDev,pPDev->PlotForm.LogSize.cx);
  792. pGDIInfo->szlPhysSize.cy = SPLTOENGUNITS(pPDev,pPDev->PlotForm.LogSize.cy);
  793. pGDIInfo->ptlPhysOffset.x = SPLTOENGUNITS(pPDev,pPDev->PlotForm.PhyOrg.x);
  794. pGDIInfo->ptlPhysOffset.y = SPLTOENGUNITS(pPDev,pPDev->PlotForm.PhyOrg.y);
  795. PLOTDBG(DBG_GDICAPS, ("GDICAPS: PhySize= %d x %d, PhyOff=(%ld, %ld)",
  796. pGDIInfo->szlPhysSize.cx, pGDIInfo->szlPhysSize.cy,
  797. pGDIInfo->ptlPhysOffset.x, pGDIInfo->ptlPhysOffset.y));
  798. //
  799. // Assume the device has a 1:1 aspect ratio
  800. //
  801. pGDIInfo->ulLogPixelsX =
  802. pGDIInfo->ulLogPixelsY = (pPDev->lCurResolution * Scale / 100);
  803. PLOTDBG(DBG_GDICAPS, ("GDICAPS: LogPixelsX/Y = %d x %d",
  804. pGDIInfo->ulLogPixelsX, pGDIInfo->ulLogPixelsY));
  805. pGDIInfo->ulAspectX =
  806. pGDIInfo->ulAspectY = pPDev->lCurResolution;
  807. pGDIInfo->ulAspectXY = hypot(pGDIInfo->ulAspectX, pGDIInfo->ulAspectY);
  808. pGDIInfo->ciDevice = pPDev->pPlotGPC->ci;
  809. pGDIInfo->ulDevicePelsDPI = (DWORD)pPDev->pPlotGPC->DevicePelsDPI *
  810. (DWORD)Scale / (DWORD)100;
  811. pGDIInfo->ulHTPatternSize = pPDev->pPlotGPC->HTPatternSize;
  812. pGDIInfo->flHTFlags = HT_FLAG_HAS_BLACK_DYE;
  813. pGDIInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
  814. PLOTDBG(DBG_GDICAPS, ("GDICAPS: HTPatSize=%ld, DevPelsDPI=%ld, PrimaryOrder=%ld",
  815. pGDIInfo->ulHTPatternSize, pGDIInfo->ulDevicePelsDPI,
  816. pGDIInfo->ulPrimaryOrder));
  817. //
  818. // If the device is a color device, then set up the Halftoning info now.
  819. //
  820. if (pPDev->PlotDM.dm.dmColor == DMCOLOR_COLOR) {
  821. //
  822. // Do this only if we really want to do color in R/G/B not C/M/Y
  823. //
  824. PLOTDBG(DBG_DEVCAPS, ("FillDeviceCaps: Doing Color Output"));
  825. pDrvHTInfo->HTPalCount = 8;
  826. pDrvHTInfo->HTBmpFormat = (BYTE)BMF_4BPP;
  827. pDrvHTInfo->AltBmpFormat = (BYTE)BMF_1BPP;
  828. pGDIInfo->ulHTOutputFormat = HT_FORMAT_4BPP;
  829. } else {
  830. pDrvHTInfo->HTPalCount = 2;
  831. pDrvHTInfo->HTBmpFormat = (BYTE)BMF_1BPP;
  832. pDrvHTInfo->AltBmpFormat = (BYTE)0xff;
  833. pGDIInfo->ulHTOutputFormat = HT_FORMAT_1BPP;
  834. //
  835. // Using this flag will give us a good benefit, the flag notifies gdi
  836. // and halftone eng. that the output from halftone will be
  837. // 0=white and 1=black
  838. // as opposed to the typical 0=black, 1=white, so that at 99% of time
  839. // we do not have to flip the B/W buffer except if CopyBits is from the
  840. // calling app.
  841. //
  842. // pGDIInfo->flHTFlags |= HT_FLAG_OUTPUT_CMY;
  843. //
  844. PLOTDBG(DBG_DEVCAPS, ("FillDeviceCaps: Doing GREY SCALE (%hs) Output",
  845. (pGDIInfo->flHTFlags & HT_FLAG_OUTPUT_CMY) ? "CMY: 0=W, 1=K" :
  846. "RGB: 0=K, 1=W"));
  847. }
  848. pGDIInfo->ulNumColors = pPDev->pPlotGPC->MaxPens;
  849. pDrvHTInfo->Flags = 0;
  850. pDrvHTInfo->PalXlate[0] = 0xff;
  851. pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
  852. pGDIInfo->cBitsPixel = 24;
  853. pGDIInfo->cPlanes = 1;
  854. //
  855. // Some other information the Engine expects us to fill in.
  856. //
  857. pGDIInfo->ulDACRed = 0;
  858. pGDIInfo->ulDACGreen = 0;
  859. pGDIInfo->ulDACBlue = 0;
  860. pGDIInfo->flRaster = 0;
  861. pGDIInfo->flTextCaps = 0;
  862. pGDIInfo->xStyleStep = 1;
  863. pGDIInfo->yStyleStep = 1;
  864. pGDIInfo->denStyleStep = PLOT_STYLE_STEP(pPDev);
  865. }
  866. BOOL
  867. FillDevInfo(
  868. PPDEV pPDev,
  869. DEVINFO *pDevInfo
  870. )
  871. /*++
  872. Routine Description:
  873. Set up the device info for this particular plotter. Some fields
  874. require calculations based on device resolution, etc.
  875. We simply fill the DevInfo structure passed to us. The calling
  876. function will take care of copying the information into the
  877. Graphics Engine's buffer.
  878. Arguments:
  879. pPDev - pointer to the PDEV data structure
  880. pDevInfo - pointer to the DEVINFO to be filled
  881. Return Value:
  882. TRUE if sucessful FALSE otherwise
  883. Author:
  884. 01-Dec-1993 Wed 00:46:00 created
  885. 10-Dec-1993 Fri 16:37:06 updated
  886. Temp. disable and move the PlotCreatePalette to EnableSurf call
  887. 17-Dec-1993 Fri 16:37:06 updated
  888. Move PlotCreatePalette to StartDoc time
  889. 05-Jan-1994 Wed 22:54:21 updated
  890. Move PenColor Reference to this file and reference that directly as
  891. DWORD generate by RGB() marco
  892. 14-Jan-1994 Fri 15:35:02 updated
  893. Remove HTPatternSize param
  894. 23-Feb-1994 Wed 13:02:09 updated
  895. Make sure we return GCAPS_HALFTONE so that we will get DrvStretchBlt()
  896. callback
  897. Revision History:
  898. --*/
  899. {
  900. //
  901. // Start with a clean slate.
  902. //
  903. ZeroMemory(pDevInfo, sizeof(DEVINFO));
  904. //
  905. // fill in the graphics capabilities flags we know we can handle at
  906. // the very least.
  907. //
  908. pDevInfo->flGraphicsCaps = GCAPS_ALTERNATEFILL |
  909. GCAPS_HORIZSTRIKE |
  910. GCAPS_VERTSTRIKE |
  911. GCAPS_VECTORFONT;
  912. //
  913. // If RGB mode is on for color handling then text can be opaque
  914. //
  915. if (IS_RASTER(pPDev)) {
  916. pDevInfo->flGraphicsCaps |= GCAPS_HALFTONE;
  917. if (IS_COLOR(pPDev)) {
  918. pDevInfo->flGraphicsCaps |= GCAPS_OPAQUERECT;
  919. }
  920. }
  921. //
  922. // Check and set the BEZIER capability of the device....
  923. //
  924. if (IS_BEZIER(pPDev)) {
  925. pDevInfo->flGraphicsCaps |= GCAPS_BEZIERS;
  926. }
  927. if (IS_WINDINGFILL(pPDev)) {
  928. pDevInfo->flGraphicsCaps |= GCAPS_WINDINGFILL;
  929. }
  930. //
  931. // We don't process DrvDitherColor (perhaps later?), so set the size of
  932. // the Dither Brush to 0 to indicate this to the engine. THIS IS IN THE
  933. // SPEC FOR DrvDitherBrush () function.
  934. //
  935. pDevInfo->cxDither = 0;
  936. pDevInfo->cyDither = 0;
  937. //
  938. // the following line is set by PH. According to PH, we need
  939. // to have 16 colors. We cannot only have 9 colors (for pen plotter).
  940. //
  941. //
  942. // 01-Dec-1993 Wed 01:31:16 updated
  943. // The reason that engine need 16 colors is it optimized by using bit 3
  944. // as duplicate bit (used only bit 0/1/2) and bit 3 always mask off, so
  945. // that engine can do faster comparsion
  946. //
  947. //
  948. // If its a raster device, tell the engine that we are a 24 bit color
  949. // device. This way we get the max resolution for bitmaps and brushes
  950. // and can reducedown as required.
  951. //
  952. if (IS_RASTER(pPDev)) {
  953. pDevInfo->iDitherFormat = BMF_24BPP;
  954. } else {
  955. pDevInfo->iDitherFormat = BMF_4BPP;
  956. }
  957. if (pPDev->hPalDefault) {
  958. EngDeletePalette(pPDev->hPalDefault);
  959. pPDev->hPalDefault = NULL;
  960. }
  961. //
  962. // Create the Pen palette based only on the total number of pens the
  963. // device can handle.
  964. //
  965. if (IS_RASTER(pPDev)) {
  966. //
  967. // This is a raster device, we will always make it a 24-bit device so
  968. // the engine will pass back max color info and we can dither/halftone
  969. // as we see fit. If we don't do this, the Engine will reduce bitmaps
  970. // to our color space before passing the bitmaps onto us.
  971. //
  972. if (!(pDevInfo->hpalDefault =
  973. EngCreatePalette(PAL_BGR, 0, 0, 0, 0, 0))) {
  974. //
  975. // The create failed so raise an error
  976. //
  977. PLOTERR(("FillDevInfo: EngCreatePalette(PAL_BGR) failed."));
  978. return(FALSE);
  979. }
  980. } else {
  981. DWORD DevColor[MAX_PENPLOTTER_PENS + 2];
  982. PDWORD pdwCur;
  983. PPENDATA pPenData;
  984. PALENTRY PalEntry;
  985. UINT cPens;
  986. extern PALENTRY PlotPenPal[];
  987. PLOTASSERT(1, "Too many pens defined for pen plotter (%ld)",
  988. (pPDev->pPlotGPC->Pens.Count <= MAX_PENPLOTTER_PENS),
  989. pPDev->pPlotGPC->Pens.Count);
  990. if (pPDev->pPlotGPC->Pens.Count > MAX_PENPLOTTER_PENS)
  991. {
  992. return(FALSE);
  993. }
  994. //
  995. // Get the start of where to fill colors
  996. //
  997. pdwCur = &DevColor[0];
  998. //
  999. // 1st Entry is always WHITE
  1000. //
  1001. *pdwCur++ = RGB(255, 255, 255);
  1002. //
  1003. // Now go into a loop loading up the rest of the colors
  1004. //
  1005. PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = 255:255:255", 0));
  1006. for (cPens = 1, pPenData = (PPENDATA)pPDev->pPlotGPC->Pens.pData;
  1007. cPens <= (UINT)pPDev->pPlotGPC->Pens.Count;
  1008. pPenData++) {
  1009. //
  1010. // Place the RGB value into the palette
  1011. //
  1012. PalEntry = PlotPenPal[pPenData->ColorIdx];
  1013. *pdwCur++ = RGB(PalEntry.R, PalEntry.G, PalEntry.B);
  1014. PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = %03ld:%03ld:%03ld",
  1015. cPens,
  1016. (LONG)PalEntry.R, (LONG)PalEntry.G, (LONG)PalEntry.B));
  1017. //
  1018. // Track total number of pens defined
  1019. //
  1020. ++cPens;
  1021. }
  1022. //
  1023. // Last Pen is BRIGHT YELLOW WHITE, this is done so that a non-white
  1024. // will map to this pen, in order to effect painting on the device.
  1025. // Otherwise, if a non-white pen, gets mapped to white, nothing
  1026. // would get rendered on the surface.
  1027. //
  1028. *pdwCur++ = RGB(255, 255, 254);
  1029. cPens++;
  1030. PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = 255:255:254", cPens - 1));
  1031. //
  1032. // Now create the engine palette
  1033. //
  1034. if (!(pDevInfo->hpalDefault = EngCreatePalette(PAL_INDEXED,
  1035. cPens,
  1036. DevColor,
  1037. 0,
  1038. 0,
  1039. 0))) {
  1040. //
  1041. // The create failed so raise an error
  1042. //
  1043. PLOTERR(("FillDevInfo: EngCreatePalette(PAL_INDEXED=%ld) failed.",
  1044. cPens));
  1045. return(FALSE);
  1046. }
  1047. }
  1048. //
  1049. // Save the created palette / later we need to destroy it.
  1050. //
  1051. pPDev->hPalDefault = pDevInfo->hpalDefault;
  1052. return(TRUE);
  1053. }
  1054. BOOL
  1055. CommonStartPDEV(
  1056. PDEV *pPDev,
  1057. DEVMODEW *pPlotDMIn,
  1058. ULONG cPatterns,
  1059. HSURF *phsurfPatterns,
  1060. ULONG cjDevCaps,
  1061. ULONG *pDevCaps,
  1062. ULONG cjDevInfo,
  1063. DEVINFO *pDevInfo
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. Function to perform the PDEV initialization. This is common to
  1068. DrvEnablePDEV and DrvResetPDEV. The individual functions
  1069. do whatever is required before calling into here.
  1070. Arguments:
  1071. pPDev - the pPDev which we returned in DrvEnablePDEV
  1072. pPlotDMIn - Pointer to the DEVMODE data structure
  1073. cPatterns - Count of patterns to be set in phsurfPatterns
  1074. phsurfPatterns - pointer to the standard pattern HSURF array
  1075. cjDevCaps - total size of pDevCaps pointed to.
  1076. pDevCaps - pointer to the device cap DWORDs
  1077. cjDevInfo - total size of pDevInfo pointed to
  1078. pDevInfo - pointer to the DEVINFO data structure
  1079. Return Value:
  1080. BOOLEAN
  1081. Author:
  1082. 23-Nov-1993 Tue 20:13:10 created
  1083. Re-write
  1084. 05-Jan-1994 Wed 23:34:18 updated
  1085. Make PlotXDPI for the Pen Plotter rather than PLOTTER_UNITS_DPI
  1086. 06-Jan-1994 Thu 13:10:11 updated
  1087. Change RasterDPI always be the resoluton reports back to the engine
  1088. Revision History:
  1089. --*/
  1090. {
  1091. GDIINFO GdiInfo;
  1092. DEVINFO DevInfo;
  1093. DWORD dmErrBits;
  1094. //
  1095. // Validate the DEVMODE structure passed in by the user, If OK, set the
  1096. // appropriate fields in the PDEV, the validateSetPlotDM() will always
  1097. // return a valid PLOTDEVMODE so we just use it. Any valid DM info will
  1098. // merged into the final DEVMODE
  1099. //
  1100. if (dmErrBits = ValidateSetPLOTDM(pPDev->hPrinter,
  1101. pPDev->pPlotGPC,
  1102. pPDev->PlotDM.dm.dmDeviceName,
  1103. (PPLOTDEVMODE)pPlotDMIn,
  1104. &(pPDev->PlotDM),
  1105. &(pPDev->CurForm))) {
  1106. PLOTWARN(("CommonStartPDEV: ValidateSetPLOTDM() ErrBits=%08lx",
  1107. dmErrBits));
  1108. }
  1109. //
  1110. // fill in our PDEV structure...
  1111. //
  1112. // The RasterDPI will be used for raster printer resolution, for pen
  1113. // plotters this is the GPC's ideal resolution.
  1114. //
  1115. pPDev->lCurResolution = (LONG)pPDev->pPlotGPC->RasterXDPI;
  1116. PLOTDBG(DBG_GDICAPS, ("CURRENT Resolution = %ld", pPDev->lCurResolution));
  1117. SetPlotForm(&(pPDev->PlotForm),
  1118. pPDev->pPlotGPC,
  1119. &(pPDev->CurPaper),
  1120. &(pPDev->CurForm),
  1121. &(pPDev->PlotDM),
  1122. &(pPDev->PPData));
  1123. //
  1124. // fill in the device capabilities in GDIINFO data structure for the engine
  1125. //
  1126. if ((cjDevCaps) && (pDevCaps)) {
  1127. FillDeviceCaps(pPDev, &GdiInfo);
  1128. CopyMemory(pDevCaps, &GdiInfo, min(cjDevCaps, sizeof(GDIINFO)));
  1129. }
  1130. //
  1131. // Fill in DevInfo data structrue
  1132. //
  1133. if ((cjDevInfo) && (pDevInfo)) {
  1134. if (!FillDevInfo(pPDev, &DevInfo)) {
  1135. return(FALSE);
  1136. }
  1137. CopyMemory(pDevInfo, &DevInfo, min(cjDevInfo, sizeof(DEVINFO)));
  1138. }
  1139. //
  1140. // Set it to NULL so that the engine can create halftone one for us
  1141. //
  1142. if ((cPatterns) && (phsurfPatterns)) {
  1143. ZeroMemory(phsurfPatterns, sizeof(HSURF) * cPatterns);
  1144. }
  1145. return(TRUE);
  1146. }