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.

1358 lines
42 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: enumgdi.cxx
  3. *
  4. * Enumeration routines.
  5. * hefs
  6. * Created: 28-Mar-1992 16:18:45
  7. * Author: Gilman Wong [gilmanw]
  8. *
  9. * Copyright (c) 1992-199 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. // gaclrEnumColorTable
  14. //
  15. // Colors used for GreEnumPens and GreEnumBrushes. This color table is
  16. // set up so that:
  17. //
  18. // - the first 2 entries are for monochrome devices
  19. //
  20. // - the first 8 entries are for 8-color devices
  21. //
  22. // - the first 16 are for 4 BPP color devices
  23. //
  24. // - the first 20 are for 8 BPP and up color devices
  25. static COLORREF
  26. gaclrEnumColorTable[] = { 0x00000000, // black
  27. 0x00ffffff, // white (monochrome)
  28. 0x000000ff, // red
  29. 0x0000ff00, // green
  30. 0x0000ffff, // yellow
  31. 0x00ff0000, // blue
  32. 0x00ff00ff, // magenta
  33. 0x00ffff00, // cyan (EGA hi-intensity)
  34. 0x00808080, // dark grey
  35. 0x00c0c0c0, // light grey
  36. 0x00000080, // red
  37. 0x00008000, // green
  38. 0x00008080, // yellow
  39. 0x00800000, // blue
  40. 0x00800080, // magenta
  41. 0x00808000, // cyan (EGA lo-intensity)
  42. 0x00c0dcc0, // money green
  43. 0x00f0c8a4, // cool blue
  44. 0x00f0fbff, // off white
  45. 0x00a4a0a0 // med grey (extra colors)
  46. };
  47. static ULONG gulEnumColorTableSize = sizeof(gaclrEnumColorTable) / sizeof(COLORREF);
  48. #define ECT_1BPP 2 // use this many colors for 1 BPP
  49. #define ECT_EGA 8 // use this many colors for EGA
  50. #define ECT_4BPP 16 // use this many colors for 4 BPP
  51. #define ECT_8BPP min(gulEnumColorTableSize, 256) // use this many colors for 8 BPP
  52. #define ENUM_FILTER_NONE 0
  53. #define ENUM_FILTER_TT 1
  54. #define ENUM_FILTER_NONTT 2
  55. // gaulEnumPenStyles
  56. //
  57. // Pen styles used for GreEnumPens.
  58. static ULONG
  59. gaulPenStyles[] = { PS_SOLID,
  60. PS_DASH,
  61. PS_DOT,
  62. PS_DASHDOT,
  63. PS_DASHDOTDOT
  64. };
  65. static ULONG gulPenStylesTableSize = sizeof(gaulPenStyles) / sizeof(ULONG);
  66. // gaulEnumBrushStyles
  67. //
  68. // Brush hatch styles used for GreEnumBrushes.
  69. ULONG
  70. gaulHatchStyles[] = { HS_HORIZONTAL,
  71. HS_VERTICAL,
  72. HS_FDIAGONAL,
  73. HS_BDIAGONAL,
  74. HS_CROSS,
  75. HS_DIAGCROSS
  76. };
  77. static ULONG gulHatchStylesTableSize = sizeof(gaulHatchStyles) / sizeof(ULONG);
  78. /******************************Public*Routine******************************\
  79. * NtGdiEnumObjects()
  80. *
  81. *
  82. * Returns:
  83. * Number of objects copied into the return buffer. If buffer is NULL,
  84. * then the object capacity needed for the buffer is returned. If an
  85. * error occurs, then ERROR is returned.
  86. *
  87. \**************************************************************************/
  88. ULONG
  89. APIENTRY
  90. NtGdiEnumObjects(
  91. HDC hdc,
  92. int iObjectType,
  93. ULONG cjBuf,
  94. PVOID pvBuf
  95. )
  96. {
  97. ULONG cRet = ERROR;
  98. if ( (cjBuf == 0) == (pvBuf == (PVOID) NULL) )
  99. {
  100. // Create and validate DC user object.
  101. DCOBJ dco(hdc);
  102. if (dco.bValid())
  103. {
  104. PDEVOBJ pdo(dco.hdev());
  105. // For color devices, we grab the colors out of the
  106. // gaclrEnumColorTable color table. For better results, a
  107. // driver should implement DrvEnumObj.
  108. ULONG cclrDevice = pdo.GdiInfoNotDynamic()->ulNumColors;
  109. ULONG cObjects;
  110. //
  111. // Determine the number of colors to grab out of the table.
  112. //
  113. if ( cclrDevice >= ECT_8BPP )
  114. cclrDevice = ECT_8BPP;
  115. else if ( cclrDevice >= ECT_4BPP )
  116. cclrDevice = ECT_4BPP;
  117. else if ( cclrDevice >= ECT_EGA )
  118. cclrDevice = ECT_EGA;
  119. else if ( cclrDevice >= ECT_1BPP )
  120. cclrDevice = ECT_1BPP;
  121. switch (iObjectType)
  122. {
  123. case OBJ_PEN:
  124. cObjects = cjBuf / sizeof(LOGPEN);
  125. cRet = cclrDevice * gulPenStylesTableSize;
  126. break;
  127. case OBJ_BRUSH:
  128. cObjects = cjBuf / sizeof(LOGBRUSH);
  129. cRet = cclrDevice * (gulHatchStylesTableSize + 1); // the "1" is the solid brush
  130. break;
  131. default:
  132. WARNING("NtGdiEnumObjects(): bad object type\n");
  133. return cRet;
  134. }
  135. //
  136. // If the buffer is big enough, return the data
  137. //
  138. if (cObjects >= cRet)
  139. {
  140. __try
  141. {
  142. ProbeForWrite(pvBuf, cjBuf, sizeof(DWORD));
  143. COLORREF *pclr;
  144. COLORREF *pclrEnd = gaclrEnumColorTable + cclrDevice;
  145. PULONG pulPenStyle;
  146. PULONG pulPenStyleEnd = gaulPenStyles + gulPenStylesTableSize;
  147. PULONG pulHatchStyle;
  148. PULONG pulHatchStyleEnd = gaulHatchStyles + gulHatchStylesTableSize;
  149. PLOGPEN plpBuf = ((PLOGPEN)pvBuf);
  150. PLOGBRUSH plbBuf = ((PLOGBRUSH)pvBuf);
  151. switch (iObjectType)
  152. {
  153. case OBJ_PEN:
  154. //
  155. // Fill buffer will LOGPENs of all styles, in all colors.
  156. //
  157. for (pulPenStyle = gaulPenStyles; pulPenStyle < pulPenStyleEnd; pulPenStyle += 1)
  158. {
  159. for (pclr = gaclrEnumColorTable;
  160. pclr < pclrEnd;
  161. pclr += 1)
  162. {
  163. // Fill in the LOGPEN fields.
  164. plpBuf->lopnWidth.x = 0; // nominal width
  165. plpBuf->lopnWidth.y = 0; // ignored
  166. plpBuf->lopnStyle = (UINT) *pulPenStyle;
  167. plpBuf->lopnColor = *pclr;
  168. // Next LOGPEN.
  169. plpBuf += 1;
  170. }
  171. }
  172. break;
  173. case OBJ_BRUSH:
  174. //
  175. // Fill buffer will LOGBRUSHs of BS_SOLID style, in all colors.
  176. //
  177. for (pclr = gaclrEnumColorTable; pclr < pclrEnd; pclr += 1)
  178. {
  179. // Fill in the LOGBRUSH fields.
  180. plbBuf->lbStyle = BS_SOLID;
  181. plbBuf->lbColor = *pclr;
  182. plbBuf->lbHatch = 0;
  183. // Next LOGBRUSH.
  184. plbBuf += 1;
  185. }
  186. //
  187. // Now fill the buffer with LOGBRUSHs of BS_HATCH, in all
  188. // hatch styles and colors.
  189. //
  190. for (pulHatchStyle = gaulHatchStyles; pulHatchStyle < pulHatchStyleEnd; pulHatchStyle += 1)
  191. {
  192. for (pclr = gaclrEnumColorTable;
  193. pclr < pclrEnd;
  194. pclr += 1)
  195. {
  196. // Fill in the LOGBRUSH fields.
  197. plbBuf->lbStyle = BS_HATCHED;
  198. plbBuf->lbColor = *pclr;
  199. plbBuf->lbHatch = *pulHatchStyle;
  200. // Next LOGBRUSH.
  201. plbBuf += 1;
  202. }
  203. }
  204. break;
  205. default:
  206. WARNING("NtGdiEnumObjects(): bad object type 2\n");
  207. }
  208. }
  209. __except(EXCEPTION_EXECUTE_HANDLER)
  210. {
  211. // SetLastError(GetExceptionCode());
  212. cRet = ERROR;
  213. }
  214. }
  215. else if (cObjects)
  216. {
  217. //
  218. // If the buffer is not large enough (and it is not zero)
  219. // then return an error,
  220. //
  221. cRet = ERROR;
  222. }
  223. }
  224. }
  225. return cRet;
  226. }
  227. BOOL bScanFamily(
  228. FHOBJ *pfho1, ULONG ulFilter1,
  229. FHOBJ *pfho2, ULONG ulFilter2,
  230. FHOBJ *pfho3, ULONG ulFilter3,
  231. EFSOBJ *pefsmo,
  232. ULONG iEnumType,
  233. EFFILTER_INFO *peffi,
  234. PWSZ pwszName
  235. );
  236. BOOL bScanFamilyAndFace(
  237. FHOBJ *pfhoEngFamily,
  238. FHOBJ *pfhoEngFace,
  239. FHOBJ *pfhoDevFamily,
  240. FHOBJ *pfhoDevFace,
  241. EFSOBJ *pefsmo,
  242. ULONG iEnumType,
  243. EFFILTER_INFO *peffi,
  244. PWSZ pwszName
  245. );
  246. #define EFS_DEFAULT 32
  247. /******************************Public*Routine******************************\
  248. * HEFS hefsEngineOnly
  249. *
  250. * Enumerates engine fonts only.
  251. *
  252. * PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL
  253. * pwszName is specified, then only fonts that match the given name are added
  254. * to the EFS. If a NULL pwszFace is specified, then one font of each name is
  255. * added to the EFS.
  256. *
  257. * If any of the filtering flags in the EFFILTER_INFO structure are specified,
  258. * then PFEs are tested in additional filtering stages before they are added
  259. * to the EFS.
  260. *
  261. * The EFS is allocated by this function. It is the responsibility of the
  262. * caller to ensure that the EFS is eventually freed.
  263. *
  264. * Returns:
  265. * Handle to allocated EFS object, HEFS_INVALID if an error occurs.
  266. *
  267. * History:
  268. *
  269. * 19-Aug-1996 -by- Xudong Wu [TessieW]
  270. * Add enumeration for Private PFT.
  271. *
  272. * 07-Aug-1992 -by- Gilman Wong [gilmanw]
  273. * Wrote it.
  274. \**************************************************************************/
  275. HEFS hefsEngineOnly (
  276. PWSZ pwszName, // enumerate this font family
  277. ULONG lfCharSet,
  278. ULONG iEnumType, // TRUE if processing EnumFonts()
  279. EFFILTER_INFO *peffi, // filtering information
  280. PUBLIC_PFTOBJ &pfto, // public PFT user object
  281. PUBLIC_PFTOBJ &pftop, // private PFT user object
  282. ULONG *pulCount
  283. )
  284. {
  285. // ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
  286. // so the font hash tables are stable.
  287. // Create and validate FHOBJ for engine (family list).
  288. FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
  289. if ( !fhoEngineFamily.bValid() )
  290. {
  291. WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n");
  292. return HEFS_INVALID;
  293. }
  294. // Create and validate FHOBJ for engine (face list).
  295. FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
  296. if ( !fhoEngineFace.bValid() )
  297. {
  298. WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n");
  299. return HEFS_INVALID;
  300. }
  301. // For NULL pwszName, an example of each family needs to be enumerated. In
  302. // other words, we scan ACROSS the names.
  303. if (pwszName == (PWSZ) NULL)
  304. {
  305. // Allocate a new EFSTATE for the enumeration. Use total number
  306. // of lists as a hint for the initial size. This is reasonable
  307. // since we will probably enumerate back all of the list heads.
  308. EFSMEMOBJ efsmo(fhoEngineFamily.cLists(), iEnumType);
  309. if ( !efsmo.bValid() )
  310. {
  311. WARNING("win32k!GreEnumFontOpen(): could not allocate enumeration state\n");
  312. return HEFS_INVALID;
  313. }
  314. // Enumerate engine fonts in public PFT.
  315. // For Win3.1 compatability Non-TT,TT.
  316. if ( !bScanFamily(&fhoEngineFamily, ENUM_FILTER_NONTT, &fhoEngineFamily, ENUM_FILTER_TT,
  317. (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
  318. {
  319. return HEFS_INVALID;
  320. }
  321. // Scan through private PFT if gpPFTPrivate!=NULL
  322. if (pftop.pPFT != NULL)
  323. {
  324. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  325. if ( !fhoPrivateFamily.bValid() )
  326. {
  327. WARNING("win32k!hefsEngineOnly(): cannot lock private font hash (family)\n");
  328. return HEFS_INVALID;
  329. }
  330. if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT,
  331. (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
  332. {
  333. return HEFS_INVALID;
  334. }
  335. }
  336. *pulCount = efsmo.cjEfdwTotal();
  337. // Keep the EFSTATE around.
  338. efsmo.vKeepIt();
  339. // Return the EFSOBJ handle.
  340. return efsmo.hefs();
  341. }
  342. // For non-NULL pwszName, all the fonts of a particular family are enumerated.
  343. // In other words, we scan DOWN a name.
  344. else
  345. {
  346. // Allocate a new EFSTATE. Use a default size.
  347. EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
  348. if ( !efsmo.bValid() )
  349. {
  350. WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
  351. return HEFS_INVALID;
  352. }
  353. if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  354. &efsmo, iEnumType, peffi, pwszName))
  355. {
  356. return HEFS_INVALID;
  357. }
  358. // Scan through the Privat PFT with family name lists.
  359. if (pftop.pPFT != NULL)
  360. {
  361. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  362. FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
  363. if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
  364. {
  365. WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n");
  366. return HEFS_INVALID;
  367. }
  368. if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  369. &efsmo, iEnumType, peffi, pwszName))
  370. {
  371. return HEFS_INVALID;
  372. }
  373. }
  374. // Repeat with the alternate facename (if any). Since a LOGFONT can
  375. // map via the alternate facenames, it is appropriate to enumerate the
  376. // alternate facename fonts as if they really had this face name.
  377. PFONTSUB pfsub = pfsubAlternateFacename(pwszName);
  378. PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
  379. if ( pwszAlt != (PWSZ) NULL )
  380. {
  381. // Enumerate engine fonts.
  382. if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  383. &efsmo, iEnumType, peffi, pwszAlt))
  384. {
  385. return HEFS_INVALID;
  386. }
  387. // Enumerate the private fonts.
  388. if (pftop.pPFT != NULL)
  389. {
  390. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  391. FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
  392. if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
  393. {
  394. WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n");
  395. return HEFS_INVALID;
  396. }
  397. if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  398. &efsmo, iEnumType, peffi, pwszAlt))
  399. {
  400. return HEFS_INVALID;
  401. }
  402. }
  403. // Inform the enumeration state that an alternate name was used.
  404. efsmo.vUsedAltName(pfsub);
  405. }
  406. *pulCount = efsmo.cjEfdwTotal();
  407. // Keep the EFSTATE around.
  408. efsmo.vKeepIt();
  409. // Return the EFSOBJ handle.
  410. return efsmo.hefs();
  411. }
  412. }
  413. /******************************Public*Routine******************************\
  414. * HEFS hefsDeviceAndEngine
  415. *
  416. * Enumerates device and engine fonts.
  417. *
  418. * PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL
  419. * pwszName is specified, then only fonts that match the given name are added
  420. * to the EFS. If a NULL pwszFace is specified, then one font of each name is
  421. * added to the EFS.
  422. *
  423. * If any of the filtering flags in the EFFILTER_INFO structure are specified,
  424. * then PFEs are tested in additional filtering stages before they are added
  425. * to the EFS.
  426. *
  427. * The EFS is allocated by this function. It is the responsibility of the
  428. * caller to ensure that the EFS is eventually freed.
  429. *
  430. * Returns:
  431. * Handle to allocated EFS object, HEFS_INVALID if an error occurs.
  432. *
  433. *
  434. * History:
  435. *
  436. * 18-Sept-1996 -by- Xudong Wu [TessieW]
  437. * Add the enumeration for private PFT.
  438. *
  439. * 07-Aug-1992 -by- Gilman Wong [gilmanw]
  440. * Wrote it.
  441. \**************************************************************************/
  442. HEFS hefsDeviceAndEngine (
  443. PWSZ pwszName, // enumerate this font family
  444. ULONG lfCharSet,
  445. ULONG iEnumType,
  446. EFFILTER_INFO *peffi, // filtering information
  447. PUBLIC_PFTOBJ &pfto, // public PFT user object
  448. PUBLIC_PFTOBJ &pftop, // private PFT user object
  449. PFFOBJ &pffoDevice, // PFFOBJ for device fonts
  450. PDEVOBJ &pdo, // PDEVOBJ for device
  451. ULONG *pulCount
  452. )
  453. {
  454. // ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
  455. // so the font hash tables are stable.
  456. // Create and validate FHOBJ for device (family list).
  457. FHOBJ fhoDeviceFamily(&pffoDevice.pPFF->pfhFamily);
  458. if ( !fhoDeviceFamily.bValid() )
  459. {
  460. WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (family)\n");
  461. return HEFS_INVALID;
  462. }
  463. // Create and validate FHOBJ for engine (family list).
  464. FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
  465. if ( !fhoEngineFamily.bValid() )
  466. {
  467. WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n");
  468. return HEFS_INVALID;
  469. }
  470. // Create and validate FHOBJ for device (face list).
  471. FHOBJ fhoDeviceFace(&pffoDevice.pPFF->pfhFace);
  472. if ( !fhoDeviceFace.bValid() )
  473. {
  474. WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (face)\n");
  475. return HEFS_INVALID;
  476. }
  477. // Create and validate FHOBJ for engine (face list).
  478. FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
  479. if ( !fhoEngineFace.bValid() )
  480. {
  481. WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n");
  482. return HEFS_INVALID;
  483. }
  484. // For NULL pwszName, an example of each family needs to be enumerated. In
  485. // other words, we scan ACROSS the names.
  486. if (pwszName == (PWSZ) NULL)
  487. {
  488. // Allocate a new EFSTATE for the enumeration. Use total number of lists
  489. // as a hint for the initial size. This is reasonable since we will probably
  490. // enumerate back all of the list heads.
  491. ASSERTGDI(peffi->bNonTrueTypeFilter == FALSE, "ERROR not FALSE");
  492. EFSMEMOBJ efsmo(fhoDeviceFamily.cLists() + fhoEngineFamily.cLists(), iEnumType);
  493. if ( !efsmo.bValid() )
  494. {
  495. WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
  496. return HEFS_INVALID;
  497. }
  498. //
  499. // Enumerate device and engine fonts.
  500. //
  501. if (pdo.flTextCaps() & TC_RA_ABLE)
  502. {
  503. //
  504. // For Win3.1 compatability Enum Device,Non-TT,TT
  505. // This is for Displays and PaintJets under 3.1
  506. //
  507. if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_NONTT,
  508. &fhoEngineFamily, ENUM_FILTER_TT, &efsmo, iEnumType, peffi, NULL) )
  509. {
  510. return HEFS_INVALID;
  511. }
  512. // scan through private PFT if gpPFTPrivate!=NULL
  513. if (pftop.pPFT != NULL)
  514. {
  515. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  516. if ( !fhoPrivateFamily.bValid() )
  517. {
  518. WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
  519. return HEFS_INVALID;
  520. }
  521. if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT,
  522. (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
  523. {
  524. return HEFS_INVALID;
  525. }
  526. }
  527. }
  528. #if 0
  529. // If we ever need this, this is how Postscript should do it. We would
  530. // need to call the driver at Enable Printer time to see if it's Postscript
  531. // and set a bit for quick checking here.
  532. else if (pdo.bPostScript())
  533. {
  534. //
  535. // For Win3.1 compatability Enum TT,Device,Non-TT,
  536. //
  537. if (!bScanFamily(&fhoEngineFamily, ENUM_FILTER_TT, &fhoDeviceFamily, ENUM_FILTER_NONE,
  538. &fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) )
  539. {
  540. return HEFS_INVALID;
  541. }
  542. // scan throught private PFT if gpPFTPrivate!=NULL
  543. if (pftop.pPFT != NULL)
  544. {
  545. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  546. if ( !fhoPrivateFamily.bValid() )
  547. {
  548. WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
  549. return HEFS_INVALID;
  550. }
  551. if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT,
  552. (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
  553. {
  554. return HEFS_INVALID;
  555. }
  556. }
  557. }
  558. #endif
  559. else
  560. {
  561. //
  562. // Win3.1 compatability.
  563. // Enum Device, TT, Non-TT.
  564. //
  565. if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_TT,
  566. &fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) )
  567. {
  568. return HEFS_INVALID;
  569. }
  570. if (pftop.pPFT != NULL)
  571. {
  572. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  573. if ( !fhoPrivateFamily.bValid() )
  574. {
  575. WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
  576. return HEFS_INVALID;
  577. }
  578. if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT,
  579. (FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
  580. {
  581. return HEFS_INVALID;
  582. }
  583. }
  584. }
  585. *pulCount = efsmo.cjEfdwTotal();
  586. // Keep the EFSTATE around.
  587. efsmo.vKeepIt();
  588. // Return the EFSOBJ handle.
  589. return efsmo.hefs();
  590. }
  591. else
  592. {
  593. // For non-NULL pwszName, all the fonts of a particular family are enumerated.
  594. // In other words, we scan DOWN a name.
  595. // Allocate a new EFSTATE. Use a default size.
  596. EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
  597. if ( !efsmo.bValid() )
  598. {
  599. WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
  600. return HEFS_INVALID;
  601. }
  602. // Enumerate device and engine fonts.
  603. if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace,
  604. &efsmo, iEnumType, peffi, pwszName))
  605. {
  606. return HEFS_INVALID;
  607. }
  608. // Enumerate the private fonts if any
  609. if (pftop.pPFT != NULL)
  610. {
  611. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  612. FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
  613. if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
  614. {
  615. WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n");
  616. return HEFS_INVALID;
  617. }
  618. if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  619. &efsmo, iEnumType, peffi, pwszName))
  620. {
  621. return HEFS_INVALID;
  622. }
  623. }
  624. // Repeat with the alternate facename (if any). Since a LOGFONT can
  625. // map via the alternate facenames, it is appropriate to enumerate the
  626. // alternate facename fonts as if they really had this face name.
  627. //
  628. // However, to be Win 3.1 compatible, we will NOT do this if the device
  629. // is a non-display device.
  630. //
  631. // It appears that Windows 95 no longer does this. Additionally, we need
  632. // to enumerate manufactured EE names (i.e. Arial Cyr, Arial Grk, etc)
  633. // on printer DC's as well now. If we don't we break Word Perfect 94 a 16 bit
  634. // winstone application.
  635. //
  636. //
  637. // if ( pdo.bDisplayPDEV() )
  638. {
  639. PFONTSUB pfsub = pfsubAlternateFacename(pwszName);
  640. PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
  641. if ( pwszAlt != (PWSZ) NULL )
  642. {
  643. // Enumerate device and engine fonts.
  644. if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace,
  645. &efsmo, iEnumType, peffi, pwszAlt))
  646. {
  647. return HEFS_INVALID;
  648. }
  649. // Enumerate private fonts if any
  650. if (pftop.pPFT != NULL)
  651. {
  652. FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
  653. FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
  654. if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
  655. {
  656. WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n");
  657. return HEFS_INVALID;
  658. }
  659. if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
  660. &efsmo, iEnumType, peffi, pwszAlt))
  661. {
  662. return HEFS_INVALID;
  663. }
  664. }
  665. // Inform the enumeration state that an alternate name was used.
  666. efsmo.vUsedAltName(pfsub);
  667. }
  668. }
  669. *pulCount = efsmo.cjEfdwTotal();
  670. // Keep the EFSTATE around.
  671. efsmo.vKeepIt();
  672. // Return the EFSOBJ handle.
  673. return efsmo.hefs();
  674. }
  675. }
  676. /******************************Public*Routine******************************\
  677. * ULONG ulEnumFontOpen
  678. *
  679. * First phase of the enumeration. Fonts from the engine and device are
  680. * chosen and saved in a EFSTATE (font enumeration state) object. A handle
  681. * to this object is passed back. The caller can use this handle to
  682. * initiate the second pass in which the data is sent back over the client
  683. * server interface in chunks.
  684. *
  685. * This function is also responsible for determining what types of filters
  686. * will be applied in choosing fonts for the enumeration. Filters which
  687. * are controllable are:
  688. *
  689. * TrueType filtering non-TrueType fonts are discarded
  690. *
  691. * Raster filering raster fonts are discarded
  692. *
  693. * Aspect ratio filtering fonts not matching resolution are discarded
  694. *
  695. * Returns:
  696. * EFS handle (as a ULONG) if successful, HEFS_INVALID (0) otherwise.
  697. *
  698. * Note:
  699. * The function may still return valid HEFS even if the EFSTATE is empty.
  700. *
  701. * History:
  702. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  703. * Wrote it.
  704. \**************************************************************************/
  705. ULONG_PTR GreEnumFontOpen (
  706. HDC hdc, // device to enumerate on
  707. ULONG iEnumType, // EnumFonts, EnumFontFamilies or EnumFontFamiliesEx
  708. FLONG flWin31Compat, // Win 3.1 compatibility flags
  709. ULONG cwchMax, // maximum name length (for paranoid CSR code)
  710. PWSZ pwszName, // font name to enumerate
  711. ULONG lfCharSet,
  712. ULONG *pulCount
  713. )
  714. {
  715. DONTUSE(cwchMax);
  716. HEFS hefsRet = HEFS_INVALID;
  717. //
  718. // Create and validate user object for DC.
  719. //
  720. DCOBJ dco(hdc);
  721. if(!dco.bValid())
  722. {
  723. WARNING("gdisrv!ulEnumFontOpen(): cannot access DC\n");
  724. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  725. return ((ULONG_PTR) hefsRet);
  726. }
  727. //
  728. // Get PDEV user object. We also need to make
  729. // sure that we have loaded device fonts before we go off to the font mapper.
  730. // This must be done before the semaphore is locked.
  731. //
  732. PDEVOBJ pdo(dco.hdev());
  733. ASSERTGDI (
  734. pdo.bValid(),
  735. "gdisrv!ulEnumFontOpen(): cannot access PDEV\n");
  736. if (!pdo.bGotFonts())
  737. pdo.bGetDeviceFonts();
  738. // Stabilize public PFT.
  739. SEMOBJ so(ghsemPublicPFT);
  740. // Compute font enumeration filter info.
  741. EFFILTER_INFO effi;
  742. effi.lfCharSetFilter = lfCharSet;
  743. effi.bNonTrueTypeFilter = FALSE;
  744. //
  745. // If not raster capable, then use raster font filtering.
  746. //
  747. //
  748. // If it weren't hacked, we might be able to get this info
  749. // from GetDeviceCaps(). As it is, we will assume only
  750. // plotters are non-raster capable.
  751. //
  752. effi.bRasterFilter = (pdo.ulTechnology() == DT_PLOTTER);
  753. effi.bEngineFilter = (pdo.ulTechnology() == DT_CHARSTREAM);
  754. //
  755. // Aspect ratio filter (use device's logical x and y resolutions).
  756. //
  757. // Note: [Windows 3.1 compatiblity] Aspect ratio filtering is turned ON for
  758. // non-display devices. This is because most printers in Win 3.1
  759. // do aspect ratio filtering. And since the Win 3.1 DDI gives
  760. // enumeration to the drivers, display bitmap fonts usually are not
  761. // enumerated on these devices. The NT DDI, however, gives the graphics
  762. // engine control over enumeration. So we need to provide this
  763. // compatibility here. Hopefully, all devices in Win3.1 do this
  764. // filtering, because we do now.
  765. //
  766. // Note that we check the PDEV directly rather than the DC because
  767. // DCOBJ::bDisplay() is not TRUE for display ICs (just display DCs
  768. // which are DCTYPE_DIRECT).
  769. //
  770. effi.bAspectFilter = (BOOL) ( (dco.pdc->flFontMapper() & ASPECT_FILTERING)
  771. || !pdo.bDisplayPDEV() );
  772. effi.ptlDeviceAspect.x = pdo.ulLogPixelsX();
  773. effi.ptlDeviceAspect.y = pdo.ulLogPixelsY();
  774. //
  775. // If set for TrueType only, use TrueType filtering.
  776. //
  777. effi.bTrueTypeFilter = ((gulFontInformation & FE_FILTER_TRUETYPE) != 0);
  778. //
  779. // Set the Win3.1 compatibility flag.
  780. //
  781. effi.bTrueTypeDupeFilter = (BOOL) (flWin31Compat & GACF_TTIGNORERASTERDUPE);
  782. // assume failure
  783. hefsRet = 0;
  784. {
  785. // Find the device PFF
  786. DEVICE_PFTOBJ pftoDevice;
  787. PFF *pPFF;
  788. if (pPFF = pftoDevice.pPFFGet(dco.hdev()))
  789. {
  790. PFFOBJ pffoDev(pPFF);
  791. if (pffoDev.bValid())
  792. {
  793. PUBLIC_PFTOBJ pftoPublic;
  794. PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
  795. hefsRet =
  796. hefsDeviceAndEngine(
  797. pwszName
  798. , lfCharSet
  799. , iEnumType
  800. , &effi
  801. , pftoPublic
  802. , pftoPrivate
  803. , pffoDev
  804. , pdo
  805. , pulCount
  806. );
  807. }
  808. else
  809. {
  810. WARNING("ulEnumFontOpen: invalid pffoDev\n");
  811. }
  812. }
  813. }
  814. if (!hefsRet)
  815. {
  816. PUBLIC_PFTOBJ pftoPublic;
  817. PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
  818. // If no device font PFFOBJ was found, do enumeration without a PFFOBJ.
  819. // pulls all the fonts into an enumeration state.
  820. hefsRet = hefsEngineOnly(pwszName,
  821. lfCharSet,
  822. iEnumType,
  823. &effi,
  824. pftoPublic,
  825. pftoPrivate,
  826. pulCount);
  827. }
  828. return ((ULONG_PTR) hefsRet);
  829. }
  830. /******************************Public*Routine******************************\
  831. * BOOL bEnumFontChunk
  832. *
  833. * Second phase of the enumeration. HPFEs are pulled out of the enumeration
  834. * state one-by-one, converted into an ENUMFONTDATA structure, and put into
  835. * the return buffer. The size of the return buffer is determined by the
  836. * client side and determines the granularity of the "chunking".
  837. *
  838. * This function signals the client side that the enumeration data has been
  839. * exhausted by returning FALSE. Note that it is possible that in the pass
  840. * pass through here that the EFSTATE may already be empty. The caller must
  841. * check both the function return value and the pcefdw value.
  842. *
  843. * Note:
  844. * Caller should set *pcefd to the capacity of the pefp buffer.
  845. * Upon return, iEnumType will set pefb.cefp to the number of
  846. * ENUMFONTDATA structures copied into the pefb.aefd array.
  847. *
  848. * Also, pefdw is user memory, which might be asynchronously changed
  849. * at any time. So, we cannot trust any values read from that buffer.
  850. *
  851. * Returns:
  852. * TRUE if there are more to go, FALSE otherwise,
  853. *
  854. * History:
  855. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  856. * Wrote it.
  857. \**************************************************************************/
  858. BOOL bEnumFontChunk(
  859. HDC hdc, // device to enumerate on
  860. ULONG_PTR idEnum,
  861. COUNT cjEfdwTotal, // (in) capacity of buffer
  862. COUNT *pcjEfdw, // (out) number of ENUMFONTDATAs returned
  863. PENUMFONTDATAW pefdw // return buffer
  864. )
  865. {
  866. // Initialize position in buffer in which to copy data
  867. PENUMFONTDATAW pefdwCur = pefdw;
  868. *pcjEfdw = 0;
  869. // Validate DC and EnumFontState. If either fail lock bug out.
  870. DCOBJ dco(hdc);
  871. EFSOBJ efso((HEFS) idEnum);
  872. if ((!efso.bValid()) || (!dco.bValid()))
  873. {
  874. WARNING("gdisrv!bEnumFontChunk(): bad HEFS or DC handle\n");
  875. return FALSE;
  876. }
  877. // since as of 4.0 we do not go through this a chunk at the time
  878. // we must have
  879. if (cjEfdwTotal != efso.cjEfdwTotal())
  880. {
  881. WARNING("gdisrv!bEnumFontChunk(): efso.cjEfdwTotal() problem\n");
  882. return FALSE;
  883. }
  884. ASSERTGDI(cjEfdwTotal >= efso.cefe() * CJ_EFDW0,
  885. "cjEfdwTotal NOT BIG enough \n");
  886. // Counter to track number of ENUMFONTDATAW structures copied into buffer.
  887. COUNT cjEfdwCopied = 0;
  888. EFENTRY *pefe;
  889. // Before we access PFEs, grab the ghsemPublicPFT so no one can delete
  890. // PFE while we are in the loop (note that PFEs can get deleted
  891. // once we are outside of this--like between chunks!).
  892. SEMOBJ so(ghsemPublicPFT);
  893. // In each font file, try each font face
  894. // We are sure that we will not overwrite the buffer because
  895. // the size of buffer is big enough to take all the enumfont data.
  896. while((pefe = efso.pefeEnumNext()))
  897. {
  898. // Create a PFE Collect user object. We're using real handle instead of
  899. // pointers because someone may have deleted by the time we get
  900. // around to enumerating.
  901. // Get the PFE through PFE Collect object.
  902. HPFECOBJ pfeco(pefe->hpfec);
  903. PFEOBJ pfeo(pfeco.GetPFE(pefe->iFont));
  904. SIZE_T cjEfdwCur = 0;
  905. // Validate user object and copy data into buffer. Because PFE
  906. // may have been deleted between chunks, we need to check validity.
  907. PWSZ pwszFamilyOverride = NULL;
  908. BOOL bCharSetOverride = FALSE;
  909. ULONG lfCharSetOverride = DEFAULT_CHARSET;
  910. if (efso.pwszFamilyOverride())
  911. {
  912. pwszFamilyOverride = efso.pwszFamilyOverride();
  913. if (pefe->fjOverride & FJ_CHARSETOVERRIDE)
  914. {
  915. bCharSetOverride = TRUE;
  916. lfCharSetOverride = pefe->jCharSetOverride;
  917. }
  918. else
  919. {
  920. bCharSetOverride = efso.bCharSetOverride();
  921. lfCharSetOverride = (ULONG)efso.jCharSetOverride();
  922. }
  923. }
  924. else
  925. {
  926. if (pefe->fjOverride & FJ_FAMILYOVERRIDE)
  927. {
  928. pwszFamilyOverride = gpfsTable[pefe->iOverride].awchOriginal;
  929. }
  930. if (pefe->fjOverride & FJ_CHARSETOVERRIDE)
  931. {
  932. bCharSetOverride = TRUE;
  933. lfCharSetOverride = pefe->jCharSetOverride;
  934. }
  935. }
  936. if
  937. (
  938. pfeo.bValid() &&
  939. (cjEfdwCur = cjCopyFontDataW(
  940. dco,
  941. pefdwCur,
  942. pfeo,
  943. pefe->efsty,
  944. pwszFamilyOverride,
  945. lfCharSetOverride,
  946. bCharSetOverride,
  947. efso.iEnumType()
  948. ))
  949. )
  950. {
  951. cjEfdwCopied += (ULONG) cjEfdwCur;
  952. pefdwCur = (ENUMFONTDATAW *)((BYTE*)pefdwCur + cjEfdwCur);
  953. }
  954. }
  955. *pcjEfdw = cjEfdwCopied;
  956. // we are done: pefe has to be zero:
  957. ASSERTGDI(!pefe, "not all fonts are enumerated yet\n");
  958. ASSERTGDI(cjEfdwCopied <= cjEfdwTotal, "cjEfdwCopied > cjEfdwTotal\n");
  959. // true means success, it used to mean that there are more fonts to come for
  960. // enumeration. Now, we do not do "chunking" any more. Assert above makes sure
  961. // that this is the case [bodind]
  962. return TRUE;
  963. }
  964. /*************************Public*Routine********************************\
  965. * BOOL bScanTheList()
  966. *
  967. * Scan through the font hash table using the given filter mode
  968. *
  969. * History:
  970. *
  971. * 07-Nov-1996 -by- Xudong Wu [TessieW]
  972. * Wrote it.
  973. *
  974. ************************************************************************/
  975. BOOL bScanTheList(
  976. FHOBJ *pfho,
  977. ULONG ulFilter,
  978. EFSOBJ *pefsmo,
  979. ULONG iEnumType,
  980. EFFILTER_INFO *peffi,
  981. PWSZ pwszName
  982. )
  983. {
  984. BOOL bRet;
  985. if (pwszName)
  986. {
  987. bRet = pfho->bScanLists(pefsmo, pwszName, iEnumType, peffi);
  988. }
  989. else
  990. {
  991. BOOL bTempFilter;
  992. if (ulFilter == ENUM_FILTER_TT)
  993. {
  994. bTempFilter = peffi->bTrueTypeFilter;
  995. peffi->bTrueTypeFilter = TRUE;
  996. }
  997. else if (ulFilter == ENUM_FILTER_NONTT)
  998. {
  999. peffi->bNonTrueTypeFilter = TRUE;
  1000. }
  1001. bRet = pfho->bScanLists(pefsmo, iEnumType, peffi);
  1002. if (ulFilter == ENUM_FILTER_TT)
  1003. {
  1004. peffi->bTrueTypeFilter = bTempFilter;
  1005. }
  1006. else if (ulFilter == ENUM_FILTER_NONTT)
  1007. {
  1008. peffi->bNonTrueTypeFilter = FALSE;
  1009. }
  1010. }
  1011. return bRet;
  1012. }
  1013. /*************************Public*Routine********************************\
  1014. * BOOL bScanFamily()
  1015. *
  1016. * Scan through the family font hash table in the different filter
  1017. * order given by the input flag.
  1018. *
  1019. * History:
  1020. *
  1021. * 23-Oct-1996 -by- Xudong Wu [TessieW]
  1022. * Wrote it.
  1023. *
  1024. ************************************************************************/
  1025. BOOL bScanFamily(
  1026. FHOBJ *pfho1, ULONG ulFilter1,
  1027. FHOBJ *pfho2, ULONG ulFilter2,
  1028. FHOBJ *pfho3, ULONG ulFilter3,
  1029. EFSOBJ *pefsmo,
  1030. ULONG iEnumType,
  1031. EFFILTER_INFO *peffi,
  1032. PWSZ pwszName
  1033. )
  1034. {
  1035. return
  1036. (
  1037. (!pfho1 || bScanTheList(pfho1, ulFilter1, pefsmo, iEnumType, peffi, pwszName))
  1038. &&
  1039. (!pfho2 || bScanTheList(pfho2, ulFilter2, pefsmo, iEnumType, peffi, pwszName))
  1040. &&
  1041. (!pfho3 || bScanTheList(pfho3, ulFilter3, pefsmo, iEnumType, peffi, pwszName))
  1042. );
  1043. }
  1044. /*************************Public*Routine********************************\
  1045. * BOOL bScanFamilyAndFace()
  1046. *
  1047. * Frist scan through the family font hash table. If no match is found,
  1048. * scan through the face font hash table.
  1049. *
  1050. * History:
  1051. *
  1052. * 23-Oct-1996 -by- Xudong Wu [TessieW]
  1053. * Wrote it.
  1054. *
  1055. ************************************************************************/
  1056. BOOL bScanFamilyAndFace(
  1057. FHOBJ *pfhoEngFamily,
  1058. FHOBJ *pfhoEngFace,
  1059. FHOBJ *pfhoDevFamily,
  1060. FHOBJ *pfhoDevFace,
  1061. EFSOBJ *pefsmo,
  1062. ULONG iEnumType,
  1063. EFFILTER_INFO *peffi,
  1064. PWSZ pwszName
  1065. )
  1066. {
  1067. BOOL bRet = FALSE;
  1068. if (bScanFamily(pfhoDevFamily, ENUM_FILTER_NONE,
  1069. pfhoEngFamily, ENUM_FILTER_NONE,
  1070. (FHOBJ *) NULL,
  1071. 0, pefsmo, iEnumType, peffi, pwszName))
  1072. {
  1073. // If list is empty, try the face name lists, else we are done
  1074. if (pefsmo->bEmpty() )
  1075. {
  1076. bRet = bScanFamily(pfhoDevFace, ENUM_FILTER_NONE,
  1077. pfhoEngFace, ENUM_FILTER_NONE,
  1078. (FHOBJ*) NULL,
  1079. 0, pefsmo, iEnumType, peffi, pwszName);
  1080. #if DBG
  1081. if (!bRet)
  1082. WARNING("win32k!bScanFamilyAndFace(): scan face failed\n");
  1083. #endif
  1084. }
  1085. else
  1086. {
  1087. bRet = TRUE;
  1088. }
  1089. }
  1090. #if DBG
  1091. else
  1092. {
  1093. WARNING("win32k!bScanFamilyAndFace(): scan family failed\n");
  1094. }
  1095. #endif
  1096. return bRet;
  1097. }