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.

1516 lines
43 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. plotdm.c
  5. Abstract:
  6. This module contain functions which validate/set default the devmode and
  7. extented devmode (PLOTDEVMODE)
  8. Author:
  9. 15-Nov-1993 Mon 14:09:27 created
  10. [Environment:]
  11. GDI Device Driver - Plotter.
  12. [Notes:]
  13. Revision History:
  14. 15-Dec-1993 Wed 21:08:49 updated
  15. Add the default FILL_TRUETYPE flag stuff
  16. 02-Feb-1994 Wed 01:04:21 updated
  17. Change IsMetricMode() to IsA4PaperDefault(), this function right now
  18. will call RegOpenKey(), RegQueryValueEx() and RegCloseKey() to the
  19. control panel\International rather then using GetLocaleInfoW().
  20. The reason is if we call GetLocaleInfoW() then the registry key will
  21. keep opened by the API functions and since the WinSrv will never unload
  22. the driver, then the registry key will never get close, this has bad
  23. consquence which it never allowed user to save its updated profile at
  24. logoff time if this driver is used.
  25. --*/
  26. #include "precomp.h"
  27. #pragma hdrstop
  28. #define DBG_PLOTFILENAME DbgDevMode
  29. #define DBG_DEFDEVMODE 0x00000001
  30. #define DBG_CURFORM 0x00000002
  31. #define DBG_DEFPAPER 0x00000004
  32. #define DBG_A4DEFAULT 0x00000008
  33. #define DBG_ROTPAPER 0x00000010
  34. #define DBG_INTERSECTRECTL 0x00000020
  35. #define DBG_SHOWDEVMODE 0x00000040
  36. DEFINE_DBGVAR(0);
  37. //
  38. // Depends on what we have to do what we have to do
  39. //
  40. #if defined(UMODE) || defined(USERMODE_DRIVER)
  41. #define HAS_GETREGDATA 1
  42. #else
  43. #define HAS_GETREGDATA 0
  44. #endif // UMODE
  45. //
  46. // This is our default PLOTDEVMODE, we will update following fields
  47. //
  48. // dmDeviceName - Real device name passed in
  49. // dmFormName - Letter if USA and A4 if NOT USA
  50. // dmPaperSize - DMPAPER_LETTER/DMPAPER_A4
  51. // dmColor - COLOR printer = DMCOLOR_COLOR else DMCOLOR_MONOCHROME
  52. //
  53. #define A4_FORM_NAME _DefPlotDM.dm.dmDeviceName
  54. #define A4_FORM_CX _DefPlotDM.dm.dmPelsWidth
  55. #define A4_FORM_CY _DefPlotDM.dm.dmPelsHeight
  56. #define DM_PAPER_CUSTOM (DM_PAPER_WL | DM_PAPERSIZE)
  57. static const PLOTDEVMODE _DefPlotDM = {
  58. {
  59. TEXT("A4"), // dmDeviceName - filled later
  60. DM_SPECVERSION, // dmSpecVersion
  61. DRIVER_VERSION, // dmDriverVersion
  62. sizeof(DEVMODE), // dmSize
  63. PLOTDM_PRIV_SIZE, // dmDriverExtra
  64. DM_ORIENTATION |
  65. DM_PAPERSIZE |
  66. // DM_PAPERLENGTH |
  67. // DM_PAPERWIDTH |
  68. DM_SCALE |
  69. DM_COPIES |
  70. // DM_DEFAULTSOURCE | // Reserved one, must zero
  71. DM_PRINTQUALITY |
  72. DM_COLOR |
  73. // DM_DUPLEX |
  74. // DM_YRESOLUTION |
  75. // DM_TTOPTION |
  76. // DM_COLLATE |
  77. DM_FORMNAME,
  78. DMORIENT_PORTRAIT, // dmOrientation
  79. DMPAPER_LETTER, // dmPaperSize
  80. 2794, // dmPaperLength
  81. 2159, // dmPaperWidth
  82. 100, // dmScale
  83. 1, // dmCopies
  84. 0, // dmDefaultSource - RESERVED = 0
  85. DMRES_HIGH, // dmPrintQuality
  86. DMCOLOR_COLOR, // dmColor
  87. DMDUP_SIMPLEX, // dmDuplex
  88. 0, // dmYResolution
  89. 0, // dmTTOption
  90. DMCOLLATE_FALSE, // dmCollate
  91. TEXT("Letter"), // dmFormName - depends on country
  92. 0, // dmUnusedPadding - DISPLAY ONLY
  93. 0, // dmBitsPerPel - DISPLAY ONLY
  94. 2100, // dmPelsWidth - DISPLAY ONLY
  95. 2970, // dmPelsHeight - DISPLAY ONLY
  96. 0, // dmDisplayFlags - DISPLAY ONLY
  97. 0 // dmDisplayFrequency- DISPLAY ONLY
  98. },
  99. PLOTDM_PRIV_ID, // PrivID
  100. PLOTDM_PRIV_VER, // PrivVer
  101. PDMF_FILL_TRUETYPE, // default advanced dialog box
  102. {
  103. sizeof(COLORADJUSTMENT), // caSize
  104. 0, // caFlags
  105. ILLUMINANT_DEVICE_DEFAULT, // caIlluminantIndex
  106. 10000, // caRedGamma
  107. 10000, // caGreenGamma
  108. 10000, // caBlueGamma
  109. REFERENCE_BLACK_MIN, // caReferenceBlack
  110. REFERENCE_WHITE_MAX, // caReferenceWhite
  111. 0, // caContrast
  112. 0, // caBrightness
  113. 0, // caColorfulness
  114. 0 // caRedGreenTint
  115. }
  116. };
  117. #define DEFAULT_COUNTRY CTRY_UNITED_STATES
  118. #if HAS_GETREGDATA
  119. static const WCHAR wszCountryKey[] = L"Control Panel\\International";
  120. static const WCHAR wszCountryValue[] = L"iCountry";
  121. #endif
  122. BOOL
  123. IsA4PaperDefault(
  124. VOID
  125. )
  126. /*++
  127. Routine Description:
  128. This function determine if the machine user is using the letter or A4
  129. paper as default based on the country code
  130. Arguments:
  131. NONE
  132. Return Value:
  133. BOOL true if the country default paper is A4, else LETTER
  134. Author:
  135. 23-Nov-1993 Tue 17:50:25 created
  136. 02-Feb-1994 Wed 03:01:12 updated
  137. re-written so that we do open registry for the international data
  138. ourself, and we will make sure we close the all the keys opened by
  139. this function, so the system can unload the registry when the user
  140. log off.
  141. Revision History:
  142. --*/
  143. {
  144. #if HAS_GETREGDATA
  145. HKEY hKey;
  146. LONG CountryCode = DEFAULT_COUNTRY;
  147. WCHAR wszStr[16];
  148. if (RegOpenKey(HKEY_CURRENT_USER, wszCountryKey, &hKey) == ERROR_SUCCESS) {
  149. DWORD Type = REG_SZ;
  150. DWORD RetVal = sizeof(wszStr);
  151. size_t cch;
  152. if (RegQueryValueEx(hKey,
  153. (LPTSTR)wszCountryValue,
  154. NULL,
  155. &Type,
  156. (LPBYTE)wszStr,
  157. &RetVal) == ERROR_SUCCESS) {
  158. LPWSTR pwStop;
  159. PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault: Country = %s", wszStr));
  160. if (Type == REG_SZ && SUCCEEDED(StringCchLength(wszStr, CCHOF(wszStr), &cch)))
  161. {
  162. CountryCode = wcstoul(wszStr, &pwStop, 10);
  163. }
  164. else
  165. {
  166. PLOTERR(("IsA4PaperDefault: RegQueryValue '%s' FAILED", wszCountryValue));
  167. }
  168. } else {
  169. PLOTERR(("IsA4PaperDefault: RegQueryValue '%s' FAILED", wszCountryValue));
  170. }
  171. RegCloseKey(hKey);
  172. } else {
  173. PLOTERR(("IsA4PaperDefault: RegOpenKey '%s' FAILED", wszCountryKey));
  174. }
  175. if ((CountryCode == CTRY_UNITED_STATES) ||
  176. (CountryCode == CTRY_CANADA) ||
  177. ((CountryCode >= 50) && (CountryCode < 60)) ||
  178. ((CountryCode >= 500) && (CountryCode < 600))) {
  179. PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault = No, Use 'LETTER'"));
  180. return(FALSE);
  181. } else {
  182. PLOTDBG(DBG_A4DEFAULT, ("IsA4PaperDefault = Yes"));
  183. return(TRUE);
  184. }
  185. #else
  186. //
  187. // Use letter size now
  188. //
  189. return(FALSE);
  190. #endif // HAS_GETREGDATA
  191. }
  192. BOOL
  193. IntersectRECTL(
  194. PRECTL prclDest,
  195. PRECTL prclSrc
  196. )
  197. /*++
  198. Routine Description:
  199. This function intersect two RECTL data structures which specified imageable
  200. areas.
  201. Arguments:
  202. prclDest - pointer to the destination RECTL data structure, the result
  203. is written back to here
  204. prclSrc - pointer to the source RECTL data structure to be intersect
  205. with the destination RECTL
  206. Return Value:
  207. TRUE if destination is not empty, FALSE if final destination is empty
  208. Author:
  209. 20-Dec-1993 Mon 14:08:02 updated
  210. Change return value's meaning as if intersection is not empty
  211. 17-Dec-1993 Fri 14:41:10 updated
  212. Add prclDif and compare it correctly
  213. 29-Nov-1993 Mon 19:02:01 created
  214. Revision History:
  215. --*/
  216. {
  217. BOOL IsNULL = FALSE;
  218. if (prclSrc != prclDest) {
  219. //
  220. // For left/top we will set to whichever is larger.
  221. //
  222. if (prclDest->left < prclSrc->left) {
  223. prclDest->left = prclSrc->left;
  224. }
  225. if (prclDest->top < prclSrc->top) {
  226. prclDest->top = prclSrc->top;
  227. }
  228. //
  229. // For right/bottom we will set to whichever is smaller
  230. //
  231. if (prclDest->right > prclSrc->right) {
  232. prclDest->right = prclSrc->right;
  233. }
  234. if (prclDest->bottom > prclSrc->bottom) {
  235. prclDest->bottom = prclSrc->bottom;
  236. }
  237. }
  238. PLOTDBG(DBG_INTERSECTRECTL, ("IntersectRECTL: Dest = (%ld x %ld)",
  239. prclDest->right-prclDest->left, prclDest->bottom-prclDest->top));
  240. return((prclDest->right > prclDest->left) &&
  241. (prclDest->bottom > prclDest->top));
  242. }
  243. BOOL
  244. RotatePaper(
  245. PSIZEL pSize,
  246. PRECTL pImageArea,
  247. UINT RotateMode
  248. )
  249. /*++
  250. Routine Description:
  251. This function rotate a paper left 90 degree, right 90 degree or 180 degree
  252. depends on the RotateMode passed
  253. Arguments:
  254. pSize - Pointer to the size of the paper to be rotated
  255. pImageArea - Pointer to the RECTL of Imageable area
  256. RotateMode - Must be one of RM_L90, RM_R90, RM_180
  257. Return Value:
  258. No return value, but the pSize, and pImageArea pointed to location will
  259. be updated.
  260. Author:
  261. 16-Dec-1993 Thu 09:18:33 created
  262. Revision History:
  263. --*/
  264. {
  265. SIZEL Size;
  266. RECTL Margin;
  267. //
  268. // To be sucessfully rotate the paper to the left 90 degree we must know
  269. // all four sides margin before we can do anything
  270. //
  271. Size = *pSize;
  272. Margin.left = pImageArea->left;
  273. Margin.top = pImageArea->top;
  274. Margin.right = Size.cx - pImageArea->right;
  275. Margin.bottom = Size.cy - pImageArea->bottom;
  276. PLOTASSERT(0, "RotatePaper: cx size too small (%ld)",
  277. (Size.cx - Margin.left - Margin.right) > 0, Size.cx);
  278. PLOTASSERT(0, "RotatePaper: cy size too small (%ld)",
  279. (Size.cy - Margin.top - Margin.bottom) > 0, Size.cy);
  280. PLOTDBG(DBG_ROTPAPER,
  281. ("RotatePaper(%ld) FROM (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
  282. (LONG)RotateMode,
  283. pSize->cx, pSize->cy,
  284. pImageArea->left, pImageArea->top,
  285. pImageArea->right, pImageArea->bottom));
  286. //
  287. // Now we can pick the right margin/corner for the rotation
  288. //
  289. // cx Rotate Left 90 Rotate Right 90
  290. // +-------+
  291. // | T | cy cy
  292. // | | +------------+ +------------+
  293. // c| | | R | | L |
  294. // y| | c| | c| |
  295. // |L R| x| | x| |
  296. // | | |T B| |B T|
  297. // | | | | | |
  298. // | | | L | | R |
  299. // | B | +------------+ +------------+
  300. // +-------+
  301. //
  302. switch (RotateMode) {
  303. case RM_L90:
  304. pSize->cx = Size.cy;
  305. pSize->cy = Size.cx;
  306. pImageArea->left = Margin.top;
  307. pImageArea->top = Margin.right;
  308. pImageArea->right = Size.cy - Margin.bottom;
  309. pImageArea->bottom = Size.cx - Margin.left;
  310. break;
  311. case RM_R90:
  312. pSize->cx = Size.cy;
  313. pSize->cy = Size.cx;
  314. pImageArea->left = Margin.bottom;
  315. pImageArea->top = Margin.left;
  316. pImageArea->right = Size.cy - Margin.top;
  317. pImageArea->bottom = Size.cx - Margin.right;
  318. break;
  319. case RM_180:
  320. pImageArea->top = Margin.bottom;
  321. pImageArea->bottom = Size.cy - Margin.top;
  322. break;
  323. default:
  324. PLOTERR(("RotatePaper(%ld): Invalid RotateMode passed", RotateMode));
  325. return(FALSE);
  326. }
  327. PLOTDBG(DBG_ROTPAPER,
  328. ("RotatePaper(%ld) - TO (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
  329. (LONG)RotateMode,
  330. pSize->cx, pSize->cy,
  331. pImageArea->left, pImageArea->top,
  332. pImageArea->right, pImageArea->bottom));
  333. return(TRUE);
  334. }
  335. SHORT
  336. GetDefaultPaper(
  337. PPAPERINFO pPaperInfo
  338. )
  339. /*++
  340. Routine Description:
  341. This function compute the default paper name, size.
  342. Arguments:
  343. pPaperInfo - Point to the paper info which will be fill by this function
  344. Return Value:
  345. It return a SHORT value which specified the standard paper index in as
  346. DMPAPER_xxx
  347. Author:
  348. 03-Dec-1993 Fri 13:13:42 created
  349. Revision History:
  350. --*/
  351. {
  352. SHORT dmPaperSize;
  353. HRESULT hr;
  354. if (pPaperInfo == NULL) {
  355. return 0;
  356. }
  357. pPaperInfo->ImageArea.left =
  358. pPaperInfo->ImageArea.top = 0;
  359. if (IsA4PaperDefault()) {
  360. dmPaperSize = (SHORT)DMPAPER_A4;
  361. pPaperInfo->Size.cx =
  362. pPaperInfo->ImageArea.right = DMTOSPL(A4_FORM_CX);
  363. pPaperInfo->Size.cy =
  364. pPaperInfo->ImageArea.bottom = DMTOSPL(A4_FORM_CY);
  365. hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), A4_FORM_NAME);
  366. PLOTDBG(DBG_DEFPAPER, ("Pick 'A4' paper as default"));
  367. } else {
  368. dmPaperSize = (SHORT)DMPAPER_LETTER;
  369. pPaperInfo->Size.cx = (LONG)_DefPlotDM.dm.dmPaperWidth;
  370. pPaperInfo->Size.cy = (LONG)_DefPlotDM.dm.dmPaperLength;
  371. dmPaperSize = (SHORT)DMPAPER_LETTER;
  372. pPaperInfo->Size.cx =
  373. pPaperInfo->ImageArea.right = DMTOSPL(_DefPlotDM.dm.dmPaperWidth);
  374. pPaperInfo->Size.cy =
  375. pPaperInfo->ImageArea.bottom = DMTOSPL(_DefPlotDM.dm.dmPaperLength);
  376. hr = StringCchCopy(pPaperInfo->Name, CCHOF(pPaperInfo->Name), _DefPlotDM.dm.dmFormName);
  377. PLOTDBG(DBG_DEFPAPER, ("Pick 'Letter' paper as default"));
  378. }
  379. PLOTDBG(DBG_DEFPAPER, ("SetDefaultPaper: '%ls' (%ld x %ld)",
  380. pPaperInfo->Name, pPaperInfo->Size.cx, pPaperInfo->Size.cy));
  381. return(dmPaperSize);
  382. }
  383. VOID
  384. GetDefaultPlotterForm(
  385. PPLOTGPC pPlotGPC,
  386. PPAPERINFO pPaperInfo
  387. )
  388. /*++
  389. Routine Description:
  390. This function set the default loaded paper on the plotter to the first
  391. form data list in the PCD data file
  392. Arguments:
  393. pPlotGPC - Pointer to the GPC data
  394. pPaperInfo - Pointer to the paper info to be returned
  395. Return Value:
  396. TRUE if sucessful, false if failed
  397. Author:
  398. 03-Feb-1994 Thu 11:37:37 created
  399. Revision History:
  400. --*/
  401. {
  402. PFORMSRC pFS;
  403. if ((pFS = (PFORMSRC)pPlotGPC->Forms.pData) &&
  404. (pPlotGPC->Forms.Count)) {
  405. str2Wstr(pPaperInfo->Name, CCHOF(pPaperInfo->Name), pFS->Name);
  406. pPaperInfo->Size = pFS->Size;
  407. pPaperInfo->ImageArea.left = pFS->Margin.left;
  408. pPaperInfo->ImageArea.top = pFS->Margin.top;
  409. pPaperInfo->ImageArea.right = pFS->Size.cx - pFS->Margin.right;
  410. pPaperInfo->ImageArea.bottom = pFS->Size.cy - pFS->Margin.bottom;
  411. } else {
  412. PLOTERR(("GetDefaultPlotterForm: No FORM DATA in PCD, used country default"));
  413. GetDefaultPaper(pPaperInfo);
  414. }
  415. }
  416. VOID
  417. SetDefaultDMForm(
  418. PPLOTDEVMODE pPlotDM,
  419. PFORMSIZE pCurForm
  420. )
  421. /*++
  422. Routine Description:
  423. This function set the default form for the PLOTDEVMODE, these includes
  424. dmPaperSize, dmPaperWidth, dmPaperLength, dmFormName and set pCurForm
  425. if pointer is not NULL
  426. Arguments:
  427. pPlotDM - Pointer to the PLOTDEVMODE data structure
  428. pCurForm - pointer to the FORMSIZE data structure to store current
  429. default form set by this function
  430. Return Value:
  431. VOID
  432. Author:
  433. 01-Dec-1993 Wed 13:44:31 created
  434. Revision History:
  435. --*/
  436. {
  437. PAPERINFO PaperInfo;
  438. HRESULT hr;
  439. pPlotDM->dm.dmFields &= ~DM_PAPER_FIELDS;
  440. pPlotDM->dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE);
  441. pPlotDM->dm.dmPaperSize = GetDefaultPaper(&PaperInfo);
  442. pPlotDM->dm.dmPaperWidth = SPLTODM(PaperInfo.Size.cx);
  443. pPlotDM->dm.dmPaperLength = SPLTODM(PaperInfo.Size.cy);
  444. hr = StringCchCopy((LPWSTR)pPlotDM->dm.dmFormName, CCHOF(pPlotDM->dm.dmFormName), PaperInfo.Name);
  445. if (pCurForm) {
  446. pCurForm->Size = PaperInfo.Size;
  447. pCurForm->ImageArea = PaperInfo.ImageArea;
  448. }
  449. }
  450. VOID
  451. SetDefaultPLOTDM(
  452. HANDLE hPrinter,
  453. PPLOTGPC pPlotGPC,
  454. LPWSTR pwDeviceName,
  455. PPLOTDEVMODE pPlotDM,
  456. PFORMSIZE pCurForm
  457. )
  458. /*++
  459. Routine Description:
  460. This function set the default devmode based on the current pPlotGPC
  461. Arguments:
  462. hPrinter - Handle to the printer
  463. pPlotGPC - our loaded/verified GPC data.
  464. pwDeviceName - the device name passed in
  465. pPlotDM - Pointer to our ExtDevMode
  466. pCurForm - Pointer to the FORMSIZE data structure which will be
  467. updated if the pointer is not NULL, the final result of
  468. the form size/imagable area selected by the user will
  469. be written to here. the form name will be in
  470. pPlotDM->dmFormName.
  471. Return Value:
  472. VOID
  473. Author:
  474. 14-Dec-1993 Tue 20:21:48 updated
  475. Update the dmScale based on maximum the device can support
  476. 06-Dec-1993 Mon 12:49:52 updated
  477. make sure we turn off the DM_xxx bits if one of those is not valid or
  478. supported in current plotter
  479. 16-Nov-1993 Tue 13:49:27 created
  480. Revision History:
  481. --*/
  482. {
  483. WCHAR *pwchDeviceName = NULL;
  484. ULONG ulStrLen = 0;
  485. //
  486. // Device name including NULL terminator
  487. // must be equal or shorter than CCHDEVICENAME.
  488. // PREFIX doesn' take this assumption. Buffer size needs to be flexible and
  489. // should not be on stack.
  490. //
  491. if (pwDeviceName) {
  492. ulStrLen = wcslen(pwDeviceName);
  493. //
  494. // Allocate buffer to hold pwDeviceName including null terminator.
  495. // Make sure that pwDeviceName has a device name.
  496. //
  497. if (0 == ulStrLen ||
  498. !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR))))
  499. {
  500. PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n"));
  501. //
  502. // Make sure that pPlotGPC->DeviceName has a null terminator.
  503. //
  504. pPlotGPC->DeviceName[0] = (BYTE)NULL;
  505. }
  506. else
  507. {
  508. _WCPYSTR(pwchDeviceName, pwDeviceName, ulStrLen + 1);
  509. //
  510. // Make sure the PlotGPC's device name is ssync with the pDeviceName
  511. // passed.
  512. // String length must be equal or shorter than CCHDEVICENAME.
  513. // DEVMODE's device name and pPlotGPC->DeviceName can't hold a sting
  514. // longer than CCHDEVICENAME.
  515. //
  516. if (ulStrLen + 1 > CCHDEVICENAME)
  517. {
  518. PLOTERR(("SetDefaultPLOTDM: DeviceName is longer than buffer size.\n"));
  519. }
  520. else
  521. {
  522. WStr2Str(pPlotGPC->DeviceName, CCHOF(pPlotGPC->DeviceName), pwchDeviceName);
  523. }
  524. }
  525. PLOTDBG(DBG_DEFDEVMODE, ("PlotGPC DeviceName=%hs\npwDeviceName=%ls",
  526. pPlotGPC->DeviceName, pwDeviceName));
  527. } else {
  528. PLOTERR(("No DeviceName passed, using GPC's '%hs'",
  529. pPlotGPC->DeviceName));
  530. ulStrLen = strlen(pPlotGPC->DeviceName);
  531. //
  532. // Allocate buffer to hold pwDeviceName including null terminator.
  533. // Make sure that pwDeviceName has a device name.
  534. //
  535. if (0 == ulStrLen ||
  536. !(pwchDeviceName = (WCHAR*)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (ulStrLen + 1) * sizeof(WCHAR))))
  537. {
  538. PLOTERR(("SetDefaultPLOTDM: memory allocaton failed.\n"));
  539. }
  540. else
  541. {
  542. str2Wstr(pwchDeviceName, ulStrLen + 1, pPlotGPC->DeviceName);
  543. }
  544. }
  545. //
  546. // Make a default copy first then copy device name down
  547. //
  548. CopyMemory(pPlotDM, &_DefPlotDM, sizeof(PLOTDEVMODE));
  549. if (pwchDeviceName)
  550. {
  551. WCPYFIELDNAME(pPlotDM->dm.dmDeviceName, pwchDeviceName);
  552. LocalFree(pwchDeviceName);
  553. }
  554. else
  555. {
  556. pPlotDM->dm.dmDeviceName[0] = (WCHAR)NULL;
  557. }
  558. //
  559. // We must turn off the DM_xxx bits in dmFields if we do not support it,
  560. // look at default fields we copy down then update it
  561. //
  562. if (pPlotGPC->MaxScale) {
  563. if ((WORD)pPlotDM->dm.dmScale > pPlotGPC->MaxScale) {
  564. pPlotDM->dm.dmScale = (SHORT)pPlotGPC->MaxScale;
  565. }
  566. } else {
  567. pPlotDM->dm.dmFields &= ~DM_SCALE;
  568. }
  569. if (pPlotGPC->MaxCopies <= 1) {
  570. pPlotDM->dm.dmFields &= ~DM_COPIES;
  571. }
  572. if (!(pPlotGPC->MaxQuality)) {
  573. pPlotDM->dm.dmFields &= ~DM_PRINTQUALITY;
  574. }
  575. //
  576. // DEFAULT 50% quality for byte align plotter (DJ 600) to do ROP right
  577. //
  578. if (pPlotGPC->Flags & PLOTF_RASTERBYTEALIGN) {
  579. pPlotDM->dm.dmPrintQuality = DMRES_LOW;
  580. PLOTWARN(("SetDefaultPLOTDM: HACK Default Qaulity = DMRES_LOW"));
  581. }
  582. if (!(pPlotGPC->Flags & PLOTF_COLOR)) {
  583. if (pPlotGPC->Flags & PLOTF_RASTER) {
  584. pPlotDM->dm.dmFields &= ~DM_COLOR;
  585. pPlotDM->dm.dmColor = DMCOLOR_MONOCHROME;
  586. } else {
  587. PLOTASSERT(0,
  588. "SetDefaultPLOTDM: The Pen Ploter CANNOT be MONO.",
  589. (pPlotGPC->Flags & PLOTF_COLOR), 0);
  590. pPlotGPC->Flags |= PLOTF_COLOR;
  591. }
  592. }
  593. //
  594. // Set default form name based on the country
  595. //
  596. SetDefaultDMForm(pPlotDM, pCurForm);
  597. }
  598. DWORD
  599. MergePLOTDM(
  600. HANDLE hPrinter,
  601. PPLOTGPC pPlotGPC,
  602. PPLOTDEVMODE pPlotDMFrom,
  603. PPLOTDEVMODE pPlotDMTo,
  604. PFORMSIZE pCurForm
  605. )
  606. /*++
  607. Routine Description:
  608. This function merge and validate the pPlotDMTo from pPlotDMFrom. The
  609. PlotDMOut must valid
  610. Arguments:
  611. hPrinter - Handle to the printer to be checked
  612. pPlotGPC - The plotter's GPC data loaded from the file
  613. pPlotDMFrom - pointer to the input PLOTDEVMODE data structure, if can
  614. be NULL
  615. pPlotDMTo - Pointer to the output PLOTDEVMODE data structure, if
  616. pPlotDMFrom is NULL then a default PLOTDEVMODE is
  617. returned
  618. pCurForm - Pointer to the FORMSIZE data structure which will be
  619. updated if the pointer is not NULL, the final result of
  620. the form size/imagable area selected by the user will
  621. be written to here. the form name will be in
  622. pPlotDM->dmFormName.
  623. Return Value:
  624. the return value is a DWORD dmField error code which specified dmFields
  625. are invalid (DM_xxxxx in wingdi.h) if the return value has any DM_INV_xxx
  626. bits set then it should raised an error to the user.
  627. if return value is 0 then function sucessful
  628. Author:
  629. 25-Oct-1994 Tue 13:32:18 created
  630. Revision History:
  631. --*/
  632. {
  633. PLOTDEVMODE PlotDMIn;
  634. ENUMFORMPARAM EFP;
  635. DWORD dmErrFields = 0;
  636. SIZEL PaperSize;
  637. //
  638. // First: set the default PLOTDEVMODE for the output then from there
  639. // validate/settting from input devmode, if pwDeviceName passed as
  640. // NULL then it assume that pPlotDMTo alreay set and validated
  641. //
  642. // If we have invalid input devmode then this it is
  643. //
  644. if ((!pPlotDMFrom) || (!pPlotDMTo) || (!pPlotGPC)) {
  645. return(0);
  646. }
  647. //
  648. // Do some conversion here if necessary, first, copy the output one
  649. //
  650. CopyMemory(&PlotDMIn, pPlotDMTo, sizeof(PLOTDEVMODE));
  651. ConvertDevmode((PDEVMODE) pPlotDMFrom, (PDEVMODE) &PlotDMIn);
  652. PLOTDBG(DBG_SHOWDEVMODE,
  653. ("--------------- Input DEVMODE Setting -------------------"));
  654. PLOTDBG(DBG_SHOWDEVMODE,
  655. ("ValidateSetPLOTDM: dmDeviceName = %ls",
  656. (DWORD_PTR)PlotDMIn.dm.dmDeviceName));
  657. PLOTDBG(DBG_SHOWDEVMODE,
  658. ("ValidateSetPLOTDM: dmSpecVersion = %04lx",
  659. (DWORD)PlotDMIn.dm.dmSpecVersion));
  660. PLOTDBG(DBG_SHOWDEVMODE,
  661. ("ValidateSetPLOTDM: dmDriverVersion = %04lx",
  662. (DWORD)PlotDMIn.dm.dmDriverVersion));
  663. PLOTDBG(DBG_SHOWDEVMODE,
  664. ("ValidateSetPLOTDM: dmSize = %0ld (%ld)",
  665. (DWORD)PlotDMIn.dm.dmSize, sizeof(DEVMODE)));
  666. PLOTDBG(DBG_SHOWDEVMODE,
  667. ("ValidateSetPLOTDM: dmDriverExtra = %ld (%ld)",
  668. (DWORD)PlotDMIn.dm.dmDriverExtra, PLOTDM_PRIV_SIZE));
  669. PLOTDBG(DBG_SHOWDEVMODE,
  670. ("ValidateSetPLOTDM: dmFields = %08lx",
  671. (DWORD)PlotDMIn.dm.dmFields));
  672. PLOTDBG(DBG_SHOWDEVMODE,
  673. ("ValidateSetPLOTDM: dmOrientation = %ld (%hs)",
  674. (DWORD)PlotDMIn.dm.dmOrientation,
  675. (PlotDMIn.dm.dmFields & DM_ORIENTATION) ? "ON" : "OFF"));
  676. PLOTDBG(DBG_SHOWDEVMODE,
  677. ("ValidateSetPLOTDM: dmPaperSize = %ld (%hs)",
  678. (DWORD)PlotDMIn.dm.dmPaperSize,
  679. (PlotDMIn.dm.dmFields & DM_PAPERSIZE) ? "ON" : "OFF"));
  680. PLOTDBG(DBG_SHOWDEVMODE,
  681. ("ValidateSetPLOTDM: dmPaperLength = %ld (%hs)",
  682. (DWORD)PlotDMIn.dm.dmPaperLength,
  683. (PlotDMIn.dm.dmFields & DM_PAPERLENGTH) ? "ON" : "OFF"));
  684. PLOTDBG(DBG_SHOWDEVMODE,
  685. ("ValidateSetPLOTDM: dmPaperWidth = %ld (%hs)",
  686. (DWORD)PlotDMIn.dm.dmPaperWidth,
  687. (PlotDMIn.dm.dmFields & DM_PAPERWIDTH) ? "ON" : "OFF"));
  688. PLOTDBG(DBG_SHOWDEVMODE,
  689. ("ValidateSetPLOTDM: dmScale = %ld (%hs)",
  690. (DWORD)PlotDMIn.dm.dmScale,
  691. (PlotDMIn.dm.dmFields & DM_SCALE) ? "ON" : "OFF"));
  692. PLOTDBG(DBG_SHOWDEVMODE,
  693. ("ValidateSetPLOTDM: dmCopies = %ld (%hs)",
  694. (DWORD)PlotDMIn.dm.dmCopies,
  695. (PlotDMIn.dm.dmFields & DM_COPIES) ? "ON" : "OFF"));
  696. PLOTDBG(DBG_SHOWDEVMODE,
  697. ("ValidateSetPLOTDM: dmPrintQuality = %ld (%hs)",
  698. (DWORD)PlotDMIn.dm.dmPrintQuality,
  699. (PlotDMIn.dm.dmFields & DM_PRINTQUALITY) ? "ON" : "OFF"));
  700. PLOTDBG(DBG_SHOWDEVMODE,
  701. ("ValidateSetPLOTDM: dmColor = %ld (%hs)",
  702. (DWORD)PlotDMIn.dm.dmColor,
  703. (PlotDMIn.dm.dmFields & DM_COLOR) ? "ON" : "OFF"));
  704. PLOTDBG(DBG_SHOWDEVMODE,
  705. ("ValidateSetPLOTDM: dmFormName = %ls (%hs)",
  706. (DWORD_PTR)PlotDMIn.dm.dmFormName,
  707. (PlotDMIn.dm.dmFields & DM_FORMNAME) ? "ON" : "OFF"));
  708. PLOTDBG(DBG_SHOWDEVMODE,
  709. ("ValidateSetPLOTDM: Fill Truetype Font = %hs",
  710. (PlotDMIn.Flags & PDMF_FILL_TRUETYPE) ? "ON" : "OFF"));
  711. PLOTDBG(DBG_SHOWDEVMODE,
  712. ("ValidateSetPLOTDM: Plot On the Fly = %hs",
  713. (PlotDMIn.Flags & PDMF_PLOT_ON_THE_FLY) ? "ON" : "OFF"));
  714. PLOTDBG(DBG_SHOWDEVMODE,
  715. ("---------------------------------------------------------"));
  716. //
  717. // Statring checking the dmFields, *** REMEMBER: The orientation must
  718. // check before the checking the paper/form
  719. //
  720. if (PlotDMIn.dm.dmFields & DM_ORIENTATION) {
  721. switch (PlotDMIn.dm.dmOrientation) {
  722. case DMORIENT_PORTRAIT:
  723. case DMORIENT_LANDSCAPE:
  724. pPlotDMTo->dm.dmOrientation = PlotDMIn.dm.dmOrientation;
  725. pPlotDMTo->dm.dmFields |= DM_ORIENTATION;
  726. break;
  727. default:
  728. PLOTERR(("ValidatePLOTDM: Invalid dmOrientation = %ld",
  729. (LONG)PlotDMIn.dm.dmOrientation));
  730. dmErrFields |= DM_ORIENTATION;
  731. break;
  732. }
  733. }
  734. //
  735. // Validate form name so we have correct data, assume error first
  736. //
  737. dmErrFields |= (DWORD)(PlotDMIn.dm.dmFields & DM_PAPER_FIELDS);
  738. if (((PlotDMIn.dm.dmFields & DM_PAPER_CUSTOM) == DM_PAPER_CUSTOM) &&
  739. ((PlotDMIn.dm.dmPaperSize == DMPAPER_USER) ||
  740. (PlotDMIn.dm.dmPaperSize == 0)) &&
  741. (PaperSize.cx = DMTOSPL(PlotDMIn.dm.dmPaperWidth)) &&
  742. (PaperSize.cy = DMTOSPL(PlotDMIn.dm.dmPaperLength)) &&
  743. (PaperSize.cx >= MIN_SPL_FORM_CX) &&
  744. (PaperSize.cy >= MIN_SPL_FORM_CY) &&
  745. (((PaperSize.cx <= pPlotGPC->DeviceSize.cx) &&
  746. (PaperSize.cy <= pPlotGPC->DeviceSize.cy)) ||
  747. ((PaperSize.cy <= pPlotGPC->DeviceSize.cx) &&
  748. (PaperSize.cx <= pPlotGPC->DeviceSize.cy)))) {
  749. //
  750. // First choice, this is what the caller wants, we need to validate
  751. // for this device, since the size may be larger then device can
  752. // handle
  753. //
  754. pPlotDMTo->dm.dmPaperWidth = PlotDMIn.dm.dmPaperWidth;
  755. pPlotDMTo->dm.dmPaperLength = PlotDMIn.dm.dmPaperLength;
  756. pPlotDMTo->dm.dmFields &= ~DM_PAPER_FIELDS;
  757. pPlotDMTo->dm.dmFields |= DM_PAPER_CUSTOM;
  758. pPlotDMTo->dm.dmPaperSize = DMPAPER_USER;
  759. pPlotDMTo->dm.dmFormName[0] = L'\0';
  760. if (pCurForm) {
  761. //
  762. // This one is full imageable area as the widht/height
  763. //
  764. pCurForm->ImageArea.left =
  765. pCurForm->ImageArea.top = 0;
  766. pCurForm->Size.cx =
  767. pCurForm->ImageArea.right = PaperSize.cx;
  768. pCurForm->Size.cy =
  769. pCurForm->ImageArea.bottom = PaperSize.cy;
  770. }
  771. dmErrFields &= ~DM_PAPER_FIELDS; // Fine, no error
  772. PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: FORM=USER <%ld> (%ld x %ld)",
  773. PlotDMIn.dm.dmPaperSize, PaperSize.cx, PaperSize.cy));
  774. } else if ((PlotDMIn.dm.dmFields & (DM_PAPERSIZE | DM_FORMNAME)) &&
  775. (EFP.pPlotDM = pPlotDMTo) &&
  776. (EFP.pPlotGPC = pPlotGPC) &&
  777. (PlotEnumForms(hPrinter, NULL, &EFP))) {
  778. FORM_INFO_1 *pFI1;
  779. SHORT sPaperSize;
  780. BOOL Found = FALSE;
  781. //
  782. // Firstable check sPaperSize index and if not found then check formname
  783. //
  784. if ((PlotDMIn.dm.dmFields & DM_PAPERSIZE) &&
  785. ((sPaperSize = PlotDMIn.dm.dmPaperSize) >= DMPAPER_FIRST) &&
  786. (sPaperSize <= (SHORT)EFP.Count) &&
  787. (pFI1 = EFP.pFI1Base + (sPaperSize - DMPAPER_FIRST)) &&
  788. (pFI1->Flags & FI1F_VALID_SIZE)) {
  789. //
  790. // Whu..., this guy really pick a right index
  791. //
  792. Found = TRUE;
  793. PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: Fount dmPaperSize=%ld",
  794. PlotDMIn.dm.dmPaperSize));
  795. } else if (PlotDMIn.dm.dmFields & DM_FORMNAME) {
  796. //
  797. // Now go through all the formname trouble
  798. //
  799. pFI1 = EFP.pFI1Base;
  800. sPaperSize = DMPAPER_FIRST;
  801. while (EFP.Count--) {
  802. if ((pFI1->Flags & FI1F_VALID_SIZE) &&
  803. (!wcscmp(pFI1->pName, PlotDMIn.dm.dmFormName))) {
  804. PLOTDBG(DBG_CURFORM,("ValidateSetPLOTDM: Found dmFormName=%s",
  805. PlotDMIn.dm.dmFormName));
  806. Found = TRUE;
  807. break;
  808. }
  809. ++sPaperSize;
  810. ++pFI1;
  811. }
  812. }
  813. if (Found) {
  814. pPlotDMTo->dm.dmFields &= ~DM_PAPER_FIELDS;
  815. pPlotDMTo->dm.dmFields |= (DM_FORMNAME | DM_PAPERSIZE);
  816. pPlotDMTo->dm.dmPaperSize = sPaperSize;
  817. pPlotDMTo->dm.dmPaperWidth = SPLTODM(pFI1->Size.cx);
  818. pPlotDMTo->dm.dmPaperLength = SPLTODM(pFI1->Size.cy);
  819. WCPYFIELDNAME(pPlotDMTo->dm.dmFormName, pFI1->pName);
  820. PLOTDBG(DBG_CURFORM,("FI1 [%ld]: (%ld x %ld), (%ld, %ld)-(%ld, %ld)",
  821. (LONG)pPlotDMTo->dm.dmPaperSize,
  822. pFI1->Size.cx, pFI1->Size.cy,
  823. pFI1->ImageableArea.left, pFI1->ImageableArea.top,
  824. pFI1->ImageableArea.right, pFI1->ImageableArea.bottom));
  825. if (pCurForm) {
  826. pCurForm->Size = pFI1->Size;
  827. pCurForm->ImageArea = pFI1->ImageableArea;
  828. }
  829. dmErrFields &= ~DM_PAPER_FIELDS; // Fine, no error
  830. }
  831. //
  832. // Free up the memory used
  833. //
  834. LocalFree((HLOCAL)EFP.pFI1Base);
  835. }
  836. if ((PlotDMIn.dm.dmFields & DM_SCALE) &&
  837. (pPlotGPC->MaxScale)) {
  838. if ((PlotDMIn.dm.dmScale > 0) &&
  839. ((WORD)PlotDMIn.dm.dmScale <= pPlotGPC->MaxScale)) {
  840. pPlotDMTo->dm.dmScale = PlotDMIn.dm.dmScale;
  841. pPlotDMTo->dm.dmFields |= DM_SCALE;
  842. } else {
  843. PLOTERR(("ValidatePLOTDM: Invalid dmScale = %ld [%ld]",
  844. (LONG)PlotDMIn.dm.dmScale, (LONG)pPlotGPC->MaxScale));
  845. dmErrFields |= DM_SCALE;
  846. }
  847. }
  848. if (PlotDMIn.dm.dmFields & DM_COPIES) {
  849. if ((PlotDMIn.dm.dmCopies > 0) &&
  850. ((LONG)PlotDMIn.dm.dmCopies <= (LONG)pPlotGPC->MaxCopies)) {
  851. pPlotDMTo->dm.dmCopies = PlotDMIn.dm.dmCopies;
  852. pPlotDMTo->dm.dmFields |= DM_COPIES;
  853. } else {
  854. PLOTERR(("ValidatePLOTDM: Invalid dmCopies = %ld [%ld]",
  855. (LONG)PlotDMIn.dm.dmCopies, (LONG)pPlotGPC->MaxCopies));
  856. dmErrFields |= DM_COPIES;
  857. }
  858. }
  859. if (PlotDMIn.dm.dmFields & DM_PRINTQUALITY) {
  860. dmErrFields |= DM_PRINTQUALITY; // assume error, proven otherwise
  861. if (pPlotGPC->MaxQuality) {
  862. switch (PlotDMIn.dm.dmPrintQuality) {
  863. case DMRES_DRAFT:
  864. case DMRES_LOW:
  865. case DMRES_MEDIUM:
  866. case DMRES_HIGH:
  867. dmErrFields &= ~DM_PRINTQUALITY;
  868. pPlotDMTo->dm.dmPrintQuality = PlotDMIn.dm.dmPrintQuality;
  869. pPlotDMTo->dm.dmFields |= DM_PRINTQUALITY;
  870. break;
  871. }
  872. }
  873. if (dmErrFields & DM_PRINTQUALITY) {
  874. PLOTERR(("ValidatePLOTDM: Invalid dmPrintQuality = %ld [%ld]",
  875. (LONG)PlotDMIn.dm.dmPrintQuality,
  876. (LONG)pPlotGPC->MaxQuality));
  877. }
  878. }
  879. if (PlotDMIn.dm.dmFields & DM_COLOR) {
  880. dmErrFields |= DM_COLOR; // assume error, proven otherwise
  881. if (pPlotGPC->Flags & PLOTF_COLOR) {
  882. switch (PlotDMIn.dm.dmColor) {
  883. case DMCOLOR_MONOCHROME:
  884. if (!(pPlotGPC->Flags & PLOTF_RASTER)) {
  885. PLOTERR(("ValidatePLOTDM: Cannot Set Pen Plotter to MONO"));
  886. break;
  887. }
  888. case DMCOLOR_COLOR:
  889. pPlotDMTo->dm.dmColor = PlotDMIn.dm.dmColor;
  890. pPlotDMTo->dm.dmFields |= DM_COLOR;
  891. dmErrFields &= ~DM_COLOR;
  892. break;
  893. }
  894. } else if (PlotDMIn.dm.dmColor == DMCOLOR_MONOCHROME) {
  895. dmErrFields &= ~DM_COLOR;
  896. }
  897. if (dmErrFields & DM_COLOR) {
  898. PLOTERR(("ValidatePLOTDM: Invalid dmColor = %ld [%hs]",
  899. (LONG)PlotDMIn.dm.dmColor,
  900. (pPlotGPC->Flags & PLOTF_COLOR) ? "COLOR" : "MONO"));
  901. }
  902. }
  903. //
  904. // Any other dmFields we just skip because we do not have that caps, now
  905. // check if they have correct EXTDEVMODE stuff
  906. //
  907. if ((PlotDMIn.dm.dmDriverExtra == PLOTDM_PRIV_SIZE) &&
  908. (PlotDMIn.PrivID == PLOTDM_PRIV_ID) &&
  909. (PlotDMIn.PrivVer == PLOTDM_PRIV_VER)) {
  910. pPlotDMTo->Flags = (DWORD)(PlotDMIn.Flags & PDMF_ALL_BITS);
  911. pPlotDMTo->ca = PlotDMIn.ca;
  912. if (pPlotGPC->Flags & PLOTF_RASTER) {
  913. pPlotDMTo->Flags |= PDMF_FILL_TRUETYPE;
  914. } else {
  915. //
  916. // Non raster device does not have plot on the fly mode
  917. //
  918. pPlotDMTo->Flags &= ~PDMF_PLOT_ON_THE_FLY;
  919. }
  920. if (!ValidateColorAdj(&(pPlotDMTo->ca))) {
  921. dmErrFields |= DM_INV_PLOTPRIVATE;
  922. PLOTERR(("ValidatePLOTDM: Invalid coloradjusment data"));
  923. }
  924. }
  925. return(dmErrFields);
  926. }
  927. DWORD
  928. ValidateSetPLOTDM(
  929. HANDLE hPrinter,
  930. PPLOTGPC pPlotGPC,
  931. LPWSTR pwDeviceName,
  932. PPLOTDEVMODE pPlotDMIn,
  933. PPLOTDEVMODE pPlotDMOut,
  934. PFORMSIZE pCurForm
  935. )
  936. /*++
  937. Routine Description:
  938. This function set and validate the pPlotDMOut from pPlotDMIn
  939. (if not null and valid)
  940. Arguments:
  941. hPrinter - Handle to the printer to be checked
  942. pPlotGPC - The plotter's GPC data loaded from the file
  943. pwDeviceName - Device Name to be put into dmDeviceName, if NULL then
  944. the device name is set from pPlotGPC->DeviceName
  945. pPlotDMIn - pointer to the input PLOTDEVMODE data structure, if can
  946. be NULL
  947. pPlotDMOut - Pointer to the output PLOTDEVMODE data structure, if
  948. pPlotDMIn is NULL then a default PLOTDEVMODE is returned
  949. pCurForm - Pointer to the FORMSIZE data structure which will be
  950. updated if the pointer is not NULL, the final result of
  951. the form size/imagable area selected by the user will
  952. be written to here. the form name will be in
  953. pPlotDM->dmFormName.
  954. Return Value:
  955. the return value is a DWORD dmField error code which specified dmFields
  956. are invalid (DM_xxxxx in wingdi.h) if the return value has any DM_INV_xxx
  957. bits set then it should raised an error to the user.
  958. if return value is 0 then function sucessful
  959. Author:
  960. 23-Nov-1993 Tue 10:08:50 created
  961. 15-Dec-1993 Wed 21:27:52 updated
  962. Fixed bug which compare dmPaperWidth/Length to MIN_SPL_FORM_CX
  963. 18-Dec-1993 Sat 03:57:24 updated
  964. Fixed bug which reset dmFields when we checking DM_PAPERxxx and
  965. DM_FORMNAME, this turn off DM_ORIENTATION fields which let the
  966. orientation setting never stick.
  967. Also change how this fucntion set the paper fields, this function now
  968. only set DM_FORMNAME upon returned if the dmPaperSize getting larger
  969. then DMPAPER_LAST, otherwise it set DM_FORMNAME | DM_PAPERSIZE
  970. 12-Apr-1994 Tue 15:07:24 updated
  971. Make smaller spec version printable
  972. 25-Oct-1994 Tue 13:41:03 updated
  973. Change to have default as current Printer Properties setting first,
  974. Revision History:
  975. --*/
  976. {
  977. DWORD dmErrFields = 0;
  978. if (NULL == pPlotDMOut || NULL == pPlotGPC)
  979. {
  980. PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotDMOut", pPlotDMOut, 0);
  981. PLOTASSERT(1, "ValidatePLOTDM: NULL pPlotGPC", pPlotGPC, 0);
  982. return 0xFFFFFFFF;
  983. }
  984. if ((pPlotDMOut) || (pPlotGPC)) {
  985. PPRINTER_INFO_2 pPrinter2 = NULL;
  986. DWORD cbNeed;
  987. DWORD cbRet;
  988. //
  989. // First: set the default PLOTDEVMODE for the output then from there
  990. // validate/settting from input devmode, if pwDeviceName passed
  991. // as NULL then it assume that pPlotDMOut alreay set and
  992. // validated
  993. //
  994. if (pwDeviceName) {
  995. SetDefaultPLOTDM(hPrinter,
  996. pPlotGPC,
  997. pwDeviceName,
  998. pPlotDMOut,
  999. pCurForm);
  1000. PLOTDBG(DBG_DEFDEVMODE,
  1001. ("ValidateSetPLOTDM: Set Default PLOTDM DeviceName=%ls", pwDeviceName));
  1002. }
  1003. //
  1004. // Now see if we can get the current printman devmode setting as default
  1005. //
  1006. cbNeed =
  1007. cbRet = 0;
  1008. if ((!xGetPrinter(hPrinter, 2, NULL, 0, &cbNeed)) &&
  1009. (xGetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
  1010. (pPrinter2 = LocalAlloc(LMEM_FIXED, cbNeed)) &&
  1011. (xGetPrinter(hPrinter, 2, (LPBYTE)pPrinter2, cbNeed, &cbRet)) &&
  1012. (cbNeed == cbRet) &&
  1013. (pPrinter2->pDevMode)) {
  1014. PLOTDBG(DBG_DEFDEVMODE, ("ValidateSetPLOTDM: Got the PrintMan DEVMODE"));
  1015. dmErrFields = MergePLOTDM(hPrinter,
  1016. pPlotGPC,
  1017. (PPLOTDEVMODE)pPrinter2->pDevMode,
  1018. pPlotDMOut,
  1019. pCurForm);
  1020. } else {
  1021. PLOTWARN(("ValidateSetPLOTDM: CANNOT get the PrintMan's DEVMODE"));
  1022. PLOTWARN(("pPrinter2=%08lx, pDevMode=%08lx, cbNeed=%ld, cbRet=%ld, LastErr=%ld",
  1023. pPrinter2, (pPrinter2) ? pPrinter2->pDevMode : 0,
  1024. cbNeed, cbRet, xGetLastError()));
  1025. }
  1026. if (pPrinter2) {
  1027. LocalFree((HLOCAL)pPrinter2);
  1028. }
  1029. //
  1030. // Now the pPlotDMOut is validated, merge it with user's request
  1031. //
  1032. if (pPlotDMIn) {
  1033. dmErrFields = MergePLOTDM(hPrinter,
  1034. pPlotGPC,
  1035. pPlotDMIn,
  1036. pPlotDMOut,
  1037. pCurForm);
  1038. }
  1039. }
  1040. return(dmErrFields);
  1041. }