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.

3946 lines
122 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: font.c
  3. *
  4. * Created: 28-May-1991 13:01:27
  5. * Author: Gilman Wong [gilmanw]
  6. *
  7. * Copyright (c) 1990-1999 Microsoft Corporation
  8. *
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include "exehdr.h"
  13. #include "fot16.h"
  14. #include "winfont.h"
  15. // Stuf for CreateScaleableFontResource
  16. #define ALIGNMENTSHIFT 4
  17. #define ALIGNMENTCOUNT (1 << ALIGNMENTSHIFT)
  18. #define CODE_OFFSET 512
  19. #define RESOURCE_OFFSET 1024
  20. #define PRIVRESSIZE 0x80
  21. #define FONTDIRSIZINDEX 6
  22. #define NE_WINDOWS 2
  23. static
  24. WCHAR * pwszAllocNtMultiplePath(
  25. LPWSTR pwszFileName,
  26. FLONG *pfl,
  27. ULONG *pcwc,
  28. ULONG *pcFiles,
  29. BOOL bAddFR, // called by add or remove fr
  30. DWORD *pdwPidTid, // PID/TID for embedded font
  31. BOOL bChkFOT
  32. );
  33. // Define an EXE header. This will be hardcoded into the resource file.
  34. #define SIZEEXEHEADER (CJ_EXE_HDR + 25 + 39) // should be 0x80
  35. CONST static BYTE ajExeHeader[SIZEEXEHEADER] = {
  36. 0x4d, 0x5a, // unsigned short e_magic;
  37. 0x01, 0x00, // unsigned short e_cblp;
  38. 0x02, 0x00, // unsigned short e_cp;
  39. 0x00, 0x00, // unsigned short e_crlc;
  40. 0x04, 0x00, // unsigned short e_cparhdr;
  41. 0x0f, 0x00, // unsigned short e_minalloc;
  42. 0xff, 0xff, // unsigned short e_maxalloc;
  43. 0x00, 0x00, // unsigned short e_ss;
  44. 0xb8, 0x00, // unsigned short e_sp;
  45. 0x00, 0x00, // unsigned short e_csum;
  46. 0x00, 0x00, // unsigned short e_ip;
  47. 0x00, 0x00, // unsigned short e_cs;
  48. 0x40, 0x00, // unsigned short e_lfarlc;
  49. 0x00, 0x00, // unsigned short e_ovno;
  50. 0x00, 0x00, 0x00, 0x00, // unsigned short e_res[ERESWDS];
  51. 0x00, 0x00, 0x00, 0x00,
  52. 0x00, 0x00, 0x00, 0x00,
  53. 0x00, 0x00, 0x00, 0x00,
  54. 0x00, 0x00, 0x00, 0x00,
  55. 0x00, 0x00, 0x00, 0x00,
  56. 0x00, 0x00, 0x00, 0x00,
  57. 0x00, 0x00, 0x00, 0x00,
  58. SIZEEXEHEADER, 0x00, 0x00, 0x00, // long e_lfanew;
  59. // [gilmanw]
  60. // I don't know what the rest of this stuff is. Its not
  61. // in the definition of EXE_HDR that we have in gdi\inc\exehdr.h.
  62. // The string is 39 bytes, the other stuff is 25 bytes.
  63. 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,
  64. 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21,
  65. 'T','h','i','s',' ',
  66. 'i','s',' ',
  67. 'a',' ',
  68. 'T','r','u','e','T','y','p','e',' ',
  69. 'f','o','n','t',',',' ',
  70. 'n','o','t',' ',
  71. 'a',' ',
  72. 'p','r','o','g','r','a','m','.',
  73. 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x4b, 0x69, 0x65,
  74. 0x73, 0x61, 0x00
  75. };
  76. // Define a resource table. This will be hardcoded into the resource file.
  77. #define SIZEFAKERESTBL 52
  78. CONST static USHORT ausFakeResTable[SIZEFAKERESTBL/2] = {
  79. ALIGNMENTSHIFT, 0x8007, 1, 0, 0,
  80. (RESOURCE_OFFSET+PRIVRESSIZE) >> ALIGNMENTSHIFT,
  81. (0x90 >> ALIGNMENTSHIFT), 0x0c50,
  82. 0x002c, 0, 0, 0x80cc, 1, 0, 0,
  83. RESOURCE_OFFSET >> ALIGNMENTSHIFT,
  84. (PRIVRESSIZE >> ALIGNMENTSHIFT), 0x0c50, 0x8001, 0, 0, 0,
  85. 0x4607, 0x4e4f, 0x4454, 0x5249 // counted string 'FONTDIR'
  86. };
  87. // Define a New EXE header. This will be hardcoded into the resource file.
  88. #define SIZENEWEXE (CJ_NEW_EXE)
  89. CONST static USHORT ausNewExe[SIZENEWEXE/2] = {
  90. NEMAGIC, //dw NEMAGIC ;magic number
  91. 0x1005, //db 5, 10h ;version #, revision #
  92. 0xffff, //dw -1 ;offset to table entry (to be filled)
  93. 0x0002, //dw 2 ;# of bytes in entry table
  94. 0x0000, 0x0000, //dd 0 ;checksum of whole file
  95. 0x8000, 0x0000, //dw 8000h, 0, 0, 0
  96. 0x0000, 0x0000,
  97. 0x0000, 0x0000, //dd 0, 0
  98. 0x0000, 0x0000,
  99. 0x0000, 0x0000, //dw 0, 0
  100. 0xffff, //dw -1 ;size of non-resident name table
  101. SIZENEWEXE, //dw (size NewExe) ;offset to segment table
  102. SIZENEWEXE, //dw (size NewExe) ;offset to resource table
  103. SIZENEWEXE+SIZEFAKERESTBL, //dw (size NewExe)+SIZEFAKERESTBL ;off to resident name table
  104. 0xffff, //dw -1 ;offset to module reference table
  105. 0xffff, //dw -1 ;offset to imported names table
  106. 0xffff, 0x0000, //dd 0ffffh ;offset to non-resident names table
  107. 0x0000, ALIGNMENTSHIFT, //dw 0, ALIGNMENTSHIFT, 2
  108. 0x0002,
  109. NE_WINDOWS, //db NE_WINDOWS, 0
  110. 0x0000, 0x0000, //dw 0, 0, 0, 300h
  111. 0x0000, 0x0300
  112. };
  113. #define OFF_FONTDIRSIZINDEX ((2*FONTDIRSIZINDEX)+SIZEEXEHEADER+SIZENEWEXE)
  114. // Define font res string.
  115. #define SIZEFONTRES 8
  116. CONST static BYTE ajFontRes[SIZEFONTRES] = {
  117. 'F','O','N','T','R','E','S',':'
  118. };
  119. #define CJ_OUTOBJ (SIZEFFH + LF_FACESIZE + LF_FULLFACESIZE + LF_FACESIZE + PRIVRESSIZE + 1024 + 16)
  120. static
  121. VOID vNewTextMetricExWToNewTextMetricExA (
  122. NEWTEXTMETRICEXA *pntm,
  123. NTMW_INTERNAL *pntmi
  124. );
  125. typedef struct _AFRTRACKNODE
  126. {
  127. WCHAR *pwszPath;
  128. struct _AFRTRACKNODE *pafrnNext;
  129. UINT id;
  130. UINT cLoadCount;
  131. } AFRTRACKNODE;
  132. extern AFRTRACKNODE *pAFRTNodeList;
  133. AFRTRACKNODE *pAFRTNodeList;
  134. static
  135. VOID vConvertLogicalFont(
  136. ENUMLOGFONTEXDVW *pelfw,
  137. PVOID pv
  138. );
  139. ULONG cchCutOffStrLen(PSZ psz, ULONG cCutOff);
  140. ULONG
  141. cwcCutOffStrLen (
  142. PWSZ pwsz,
  143. ULONG cCutOff
  144. );
  145. // GETS ushort at (PBYTE)pv + off. both pv and off must be even
  146. #define US_GET(pv,off) ( *(PUSHORT)((PBYTE)(pv) + (off)) )
  147. #define S_GET(pv,off) ((SHORT)US_GET((pv),(off)))
  148. #if TRACK_GDI_ALLOC
  149. // Now access to these guys insn't sycnronized but they
  150. // don't ever collide anyhow, and since it's debug stuff who cares.
  151. ULONG bmgulNumMappedViews = 0;
  152. ULONG bmgulTotalSizeViews = 0;
  153. #endif
  154. /******************************Public*Routine******************************\
  155. * BOOL bMapFileUNICODEClideSide
  156. *
  157. * Similar to PosMapFile except that it takes unicode file name
  158. *
  159. * History:
  160. * Feb-05-1997 -by- Xudong Wu [tessiew]
  161. * Extend the function by adding an extra parameter bNtPath to handle the
  162. * NT path name for file mapping.
  163. *
  164. * 21-May-1991 -by- Bodin Dresevic [BodinD]
  165. * Wrote it.
  166. \**************************************************************************/
  167. BOOL bMapFileUNICODEClideSide
  168. (
  169. PWSTR pwszFileName,
  170. CLIENT_SIDE_FILEVIEW *pfvw,
  171. BOOL bNtPath
  172. )
  173. {
  174. UNICODE_STRING ObFileName;
  175. OBJECT_ATTRIBUTES ObjA;
  176. NTSTATUS rc = 0L;
  177. IO_STATUS_BLOCK iosb; // IO Status Block
  178. PWSTR pszFilePart = NULL;
  179. // NOTE PERF: this is the mode I want, but appears to be broken, so I had to
  180. // put the slower FILE_STANDARD_INFORMATION mode of query which appears to
  181. // work correctly [bodind]
  182. // FILE_END_OF_FILE_INFORMATION eof;
  183. FILE_STANDARD_INFORMATION eof;
  184. SIZE_T cjView;
  185. pfvw->hf = (HANDLE)0; // file handle
  186. pfvw->hSection = (HANDLE)0; // section handle
  187. ObFileName.Buffer = NULL;
  188. // section offset must be initialized to 0 for NtMapViewOfSection to work
  189. if (bNtPath)
  190. {
  191. RtlInitUnicodeString(&ObFileName, pwszFileName);
  192. }
  193. else //Dos path name converted to NtpathName
  194. {
  195. RtlDosPathNameToNtPathName_U(pwszFileName, &ObFileName, &pszFilePart, NULL);
  196. }
  197. InitializeObjectAttributes( &ObjA,
  198. &ObFileName,
  199. OBJ_CASE_INSENSITIVE, // case insensitive file search
  200. NULL,
  201. NULL );
  202. // NtOpenFile fails for some reason if the file is on the net unless I put this
  203. // InpersonateClient/RevertToSelf stuff around it
  204. // peform open call
  205. rc = NtOpenFile
  206. (
  207. &pfvw->hf, // store file handle here
  208. FILE_READ_DATA | SYNCHRONIZE, // desired read access
  209. &ObjA, // filename
  210. &iosb, // io result goes here
  211. FILE_SHARE_READ,
  212. FILE_SYNCHRONOUS_IO_NONALERT
  213. );
  214. if (!bNtPath && ObFileName.Buffer)
  215. {
  216. RtlFreeHeap(RtlProcessHeap(),0,ObFileName.Buffer);
  217. }
  218. // check success or fail
  219. if (!NT_SUCCESS(rc) || !NT_SUCCESS(iosb.Status))
  220. {
  221. #ifdef DEBUG_THIS_JUNK
  222. DbgPrint("bMapFileUNICODEClideSide(): NtOpenFile error code , rc = 0x%08lx , 0x%08lx\n", rc, iosb.Status);
  223. #endif // DEBUG_THIS_JUNK
  224. return FALSE;
  225. }
  226. // get the size of the file, the view should be size of the file rounded up
  227. // to a page bdry
  228. rc = NtQueryInformationFile
  229. (
  230. pfvw->hf, // IN file handle
  231. &iosb, // OUT io status block
  232. (PVOID)&eof, // OUT buffer to retrun info into
  233. sizeof(eof), // IN size of the buffer
  234. FileStandardInformation // IN query mode
  235. );
  236. // dont really want the view size, but eof file
  237. pfvw->cjView = eof.EndOfFile.LowPart;
  238. if (!NT_SUCCESS(rc))
  239. {
  240. #ifdef DEBUG_THIS_JUNK
  241. DbgPrint("bMapFileUNICODEClideSide(): NtQueryInformationFile error code 0x%08lx\n", rc);
  242. #endif // DEBUG_THIS_JUNK
  243. NtClose(pfvw->hf);
  244. return FALSE;
  245. }
  246. rc = NtCreateSection
  247. (
  248. &pfvw->hSection, // return section handle here
  249. SECTION_MAP_READ, // read access to the section
  250. (POBJECT_ATTRIBUTES)NULL, // default
  251. NULL, // size is set to the size of the file when hf != 0
  252. PAGE_READONLY, // read access to commited pages
  253. SEC_COMMIT, // all pages set to the commit state
  254. pfvw->hf // that's the file we are mapping
  255. );
  256. // check success, close the file if failed
  257. if (!NT_SUCCESS(rc))
  258. {
  259. #ifdef DEBUG_THIS_JUNK
  260. DbgPrint("bMapFileUNICODEClideSide(): NtCreateSection error code 0x%08lx\n", rc);
  261. #endif // DEBUG_THIS_JUNK
  262. NtClose(pfvw->hf);
  263. return FALSE;
  264. }
  265. // zero out *ppv so as to force the operating system to determine
  266. // the base address to be returned
  267. pfvw->pvView = (PVOID)NULL;
  268. cjView = 0L;
  269. rc = NtMapViewOfSection
  270. (
  271. pfvw->hSection, // section we are mapping
  272. NtCurrentProcess(), // process handle
  273. &pfvw->pvView, // place to return the base address of view
  274. 0L, // requested # of zero bits in the base address
  275. 0L, // commit size, (all of them commited already)
  276. NULL,
  277. &cjView, // size of the view should is returned here
  278. ViewUnmap, // do not map the view to child processess
  279. 0L, // allocation type flags
  280. PAGE_READONLY // read access to commited pages
  281. );
  282. if (!NT_SUCCESS(rc))
  283. {
  284. #ifdef DEBUG_THIS_JUNK
  285. DbgPrint("bMapFileUNICODEClideSide(): NtMapViewOfSection error code 0x%08lx\n", rc);
  286. #endif // DEBUG_THIS_JUNK
  287. NtClose(pfvw->hSection);
  288. NtClose(pfvw->hf);
  289. return FALSE;
  290. }
  291. #ifdef DEBUG_THIS_JUNK
  292. DbgPrint("cjView = 0x%lx, eof.Low = 0x%lx, eof.High = 0x%lx\n",
  293. cjView,
  294. eof.EndOfFile.LowPart,
  295. eof.EndOfFile.HighPart);
  296. #endif // DEBUG_THIS_JUNK
  297. // #define PAGE_SIZE 4096 --- this is now defined in local.h
  298. #define PAGE_ROUNDUP(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
  299. if (
  300. (eof.EndOfFile.HighPart != 0) ||
  301. (PAGE_ROUNDUP(eof.EndOfFile.LowPart) > cjView)
  302. )
  303. {
  304. #ifdef DEBUG_THIS_JUNK
  305. DbgPrint(
  306. "bMapFileUNICODEClideSide(): eof.HighPart = 0x%lx, eof.LowPart = 0x%lx, cjView = 0x%lx\n",
  307. eof.EndOfFile.HighPart, PAGE_ROUNDUP(eof.EndOfFile.LowPart), cjView
  308. );
  309. #endif // DEBUG_THIS_JUNK
  310. rc = STATUS_UNSUCCESSFUL;
  311. }
  312. if (!NT_SUCCESS(rc) || (pfvw->cjView == 0))
  313. {
  314. NtClose(pfvw->hSection);
  315. NtClose(pfvw->hf);
  316. return FALSE;
  317. }
  318. else if (pfvw->cjView == 0)
  319. {
  320. #if DBG
  321. DbgPrint("gdisrvl!bMapFileUNICODEClideSide(): WARNING--empty file %ws\n", pwszFileName);
  322. #endif
  323. vUnmapFileClideSide(pfvw);
  324. return FALSE;
  325. }
  326. else
  327. {
  328. return TRUE;
  329. }
  330. }
  331. /******************************Public*Routine******************************\
  332. * vUnmapFileClideSide
  333. *
  334. * Unmaps file whose view is based at pv
  335. *
  336. * 14-Dec-1990 -by- Bodin Dresevic [BodinD]
  337. * Wrote it.
  338. \**************************************************************************/
  339. VOID vUnmapFileClideSide(PCLIENT_SIDE_FILEVIEW pfvw)
  340. {
  341. #if TRACK_GDI_ALLOC
  342. // Now access to these guys insn't sycnronized but they (we hope)
  343. // don't ever collide anyhow, and since it's debug stuff who cares.
  344. bmgulNumMappedViews -= 1;
  345. bmgulTotalSizeViews -= PAGE_ROUNDUP(pfvw->cjView);
  346. // DbgPrint("UnMapping %lu %lu\n",pfvw->cjView,PAGE_ROUNDUP(pfvw->cjView));
  347. #endif
  348. NtUnmapViewOfSection(NtCurrentProcess(),pfvw->pvView);
  349. //
  350. // now close section handle
  351. //
  352. NtClose(pfvw->hSection);
  353. //
  354. // close file handle. other processes can now open this file for access
  355. //
  356. NtClose(pfvw->hf);
  357. //
  358. // prevent accidental use
  359. //
  360. pfvw->pvView = NULL;
  361. pfvw->hf = (HANDLE)0;
  362. pfvw->hSection = (HANDLE)0;
  363. pfvw->cjView = 0;
  364. }
  365. /******************************Public*Routine******************************\
  366. *
  367. * BOOL bVerifyFOT
  368. *
  369. * Effects: verify that that a file is valid fot file
  370. *
  371. *
  372. * History:
  373. * 29-Jan-1992 -by- Bodin Dresevic [BodinD]
  374. * Wrote it.
  375. \**************************************************************************/
  376. static
  377. BOOL bVerifyFOT
  378. (
  379. PCLIENT_SIDE_FILEVIEW pfvw,
  380. PWINRESDATA pwrd,
  381. FLONG *pflEmbed,
  382. DWORD *pdwPidTid
  383. )
  384. {
  385. PBYTE pjNewExe; // ptr to the beginning of the new exe hdr
  386. PBYTE pjResType; // ptr to the beginning of TYPEINFO struct
  387. ULONG iResID; // resource type id
  388. PBYTE pjData;
  389. ULONG ulLength;
  390. ULONG ulNameID;
  391. ULONG crn;
  392. pwrd->pvView = pfvw->pvView;
  393. pwrd->cjView = pfvw->cjView;
  394. // Initialize embed flag to FALSE (not hidden).
  395. *pflEmbed = 0;
  396. *pdwPidTid = 0;
  397. // check the magic # at the beginning of the old header
  398. // *.TTF FILES are eliminated on the following check
  399. if (US_GET(pfvw->pvView, OFF_e_magic) != EMAGIC)
  400. {
  401. return (FALSE);
  402. }
  403. pwrd->dpNewExe = (PTRDIFF)READ_DWORD((PBYTE)pfvw->pvView + OFF_e_lfanew);
  404. // make sure that offset is consistent
  405. if ((ULONG)pwrd->dpNewExe > pwrd->cjView)
  406. {
  407. return FALSE;
  408. }
  409. pjNewExe = (PBYTE)pfvw->pvView + pwrd->dpNewExe;
  410. if (US_GET(pjNewExe, OFF_ne_magic) != NEMAGIC)
  411. {
  412. return (FALSE);
  413. }
  414. pwrd->cjResTab = (ULONG)(US_GET(pjNewExe, OFF_ne_restab) -
  415. US_GET(pjNewExe, OFF_ne_rsrctab));
  416. if (pwrd->cjResTab == 0L)
  417. {
  418. // The following test is applied by DOS, so I presume that it is
  419. // legitimate. The assumption is that the resident name table
  420. // FOLLOWS the resource table directly, and that if it points to
  421. // the same location as the resource table, then there are no
  422. // resources. [bodind]
  423. WARNING("No resources in *.fot file\n");
  424. return(FALSE);
  425. }
  426. // want offset from pvView, not from pjNewExe => must add dpNewExe
  427. pwrd->dpResTab = (PTRDIFF)US_GET(pjNewExe, OFF_ne_rsrctab) + pwrd->dpNewExe;
  428. // make sure that offset is consistent
  429. if ((ULONG)pwrd->dpResTab > pwrd->cjView)
  430. {
  431. return FALSE;
  432. }
  433. // what really lies at the offset OFF_ne_rsrctab is a NEW_RSRC.rs_align field
  434. // that is used in computing resource data offsets and sizes as a shift factor.
  435. // This field occupies two bytes on the disk and the first TYPEINFO structure
  436. // follows right after. We want pwrd->dpResTab to point to the first
  437. // TYPEINFO structure, so we must add 2 to get there and subtract 2 from
  438. // the length
  439. pwrd->ulShift = (ULONG) US_GET(pfvw->pvView, pwrd->dpResTab);
  440. pwrd->dpResTab += 2;
  441. pwrd->cjResTab -= 2;
  442. // Now we want to determine where the resource data is located.
  443. // The data consists of a RSRC_TYPEINFO structure, followed by
  444. // an array of RSRC_NAMEINFO structures, which are then followed
  445. // by a RSRC_TYPEINFO structure, again followed by an array of
  446. // RSRC_NAMEINFO structures. This continues until an RSRC_TYPEINFO
  447. // structure which has a 0 in the rt_id field.
  448. pjResType = (PBYTE)pfvw->pvView + pwrd->dpResTab;
  449. iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
  450. while(iResID)
  451. {
  452. // # of NAMEINFO structures that follow = resources of this type
  453. crn = (ULONG)US_GET(pjResType, OFF_rt_nres);
  454. if ((crn == 1) && ((iResID == RT_FDIR) || (iResID == RT_PSZ)))
  455. {
  456. // this is the only interesting case, we only want a single
  457. // font directory and a single string resource for a ttf file name
  458. pjData = (PBYTE)pfvw->pvView +
  459. (US_GET(pjResType,CJ_TYPEINFO + OFF_rn_offset) << pwrd->ulShift);
  460. ulLength = (ULONG)US_GET(pjResType,CJ_TYPEINFO + OFF_rn_length) << pwrd->ulShift;
  461. ulNameID = (ULONG)US_GET(pjResType,CJ_TYPEINFO + OFF_rn_id);
  462. if (iResID == RT_FDIR)
  463. {
  464. if (ulNameID != RN_ID_FDIR)
  465. {
  466. return (FALSE); // *.fon files get eliminated here
  467. }
  468. pwrd->pjHdr = pjData + 4; // 4 bytes to the beginning of font device header
  469. pwrd->cjHdr = ulLength - 4;
  470. //
  471. // Used to check if the client thread or process is allowed to
  472. // load this font and get the FRW_EMB_PID and FRW_EMB_TID flags
  473. //
  474. // Any client thread or process is authorized to load a font if
  475. // the font isn't ebmeded ( i.e. hidden ). If
  476. // FRW_EMB_PID is set then the PID written in the
  477. // copyright string of the must equal that of the client
  478. // process. If the FRW_EMB_TID flag is set then the
  479. // TID written into the copyright
  480. // string must equal that of the client thread.
  481. //
  482. // Returns TRUE if this client process or thread is authorized
  483. // to load this font or FALSE if it isn't.
  484. //
  485. // Note: Win 3.1 hack. The LSB of Type is used by Win 3.1 as an engine type
  486. // and font embedding flag. Font embedding is a form of a "hidden
  487. // font file". The MSB of Type is the same as the fsSelection from
  488. // IFIMETRICS. (Strictly speaking, the MSB of Type is equal to the
  489. // LSB of IFIMETRICS.fsSelection).
  490. // now convert flags from the font file format to the ifi format
  491. *pflEmbed = ((READ_WORD(pwrd->pjHdr + OFF_Type) & 0x00ff) &
  492. ( PF_TID | PF_ENCAPSULATED));
  493. if (*pflEmbed)
  494. {
  495. *pflEmbed = (*pflEmbed & PF_TID) ? FRW_EMB_TID : FRW_EMB_PID;
  496. WARNING("bVerifyFOT(): notification--embedded (hidden) TT font\n");
  497. *pdwPidTid = READ_DWORD( pwrd->pjHdr + OFF_Copyright );
  498. }
  499. }
  500. else // iResID == RT_PSZ
  501. {
  502. ASSERTGDI(iResID == RT_PSZ, "bVerifyFOT!_not RT_PSZ\n");
  503. if (ulNameID != RN_ID_PSZ)
  504. {
  505. WARNING("bVerifyFOT!_RN_ID_PSZ\n");
  506. return(FALSE);
  507. }
  508. pwrd->pszNameTTF = (PSZ)pjData;
  509. pwrd->cchNameTTF = strlen(pwrd->pszNameTTF);
  510. if (ulLength < (pwrd->cchNameTTF + 1)) // 1 for terminating '\0'
  511. {
  512. WARNING("bVerifyFOT!_ pwrd->cchNameTTF\n");
  513. return(FALSE);
  514. }
  515. }
  516. }
  517. else // this is something we do not recognize as an fot file
  518. {
  519. WARNING("bVerifyFOT!_fot file with crn != 1\n");
  520. return(FALSE);
  521. }
  522. // get ptr to the new TYPEINFO struc and the new resource id
  523. pjResType = pjResType + CJ_TYPEINFO + crn * CJ_NAMEINFO;
  524. iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
  525. }
  526. return(TRUE);
  527. }
  528. /******************************Public*Routine******************************\
  529. * cGetTTFFromFOT
  530. *
  531. * Attempts to extract the TTF pathname from a given FOT file. If a return
  532. * buffer is provided (pwszTTFName !NULL), then the pathname is copied into
  533. * the buffer. Otherwise, if the buffer is NULL, the size of the buffer
  534. * (in WCHARs) needed is returned.
  535. *
  536. * Returns:
  537. * The number of characters copied into the return buffer. The number
  538. * of WCHARs needed in the buffer if the buffer is NULL. If an error
  539. * occurs, zero is returned.
  540. *
  541. * History:
  542. * 22-Apr-1992 -by- Gilman Wong [gilmanw]
  543. * Adapted from TTFD.
  544. \**************************************************************************/
  545. #define FOT_EXCEPTED 0
  546. #define FOT_NOT_FOT 1
  547. #define FOT_IS_FOT 2
  548. ULONG cGetTTFFromFOT (
  549. WCHAR *pwszFOT, // pointer to incoming FOT name
  550. ULONG cwcTTF, // size of buffer (in WCHAR)
  551. WCHAR *pwszTTF, // return TTF name in this buffer
  552. FLONG *pfl, // flags, indicate the location of the .ttf
  553. FLONG *pflEmbed, // flag, indicating PID or TID
  554. DWORD *pdwPidTid, // PID/TID for embedded font
  555. BOOL bChkFOT
  556. )
  557. {
  558. CLIENT_SIDE_FILEVIEW fvw;
  559. WINRESDATA wrd;
  560. UINT Result;
  561. WCHAR awcPath[MAX_PATH],awcFile[MAX_PATH];
  562. ULONG cNeed = 0;
  563. WCHAR *pwszTmp = NULL;
  564. ULONG cwcFOT = wcslen(pwszFOT);
  565. if (cwcFOT >= 5) // fot file has to have a form x.fot, which is at least 5 wchars long
  566. pwszTmp = &pwszFOT[cwcFOT - 4];
  567. // here we are making the exception for FOT files and we require that the file has an .FOT
  568. // extension for us to even try to recognize it as a valid FOT file.
  569. if
  570. (bChkFOT || ( pwszTmp &&
  571. (pwszTmp[0] == L'.') &&
  572. (pwszTmp[1] == L'F' || pwszTmp[1] == L'f') &&
  573. (pwszTmp[2] == L'O' || pwszTmp[2] == L'o') &&
  574. (pwszTmp[3] == L'T' || pwszTmp[3] == L't'))
  575. )
  576. {
  577. // Map the file into memory.
  578. if (bMapFileUNICODEClideSide(pwszFOT,&fvw,FALSE))
  579. {
  580. //
  581. // Check the validity of this file as fot file
  582. // and if a valid fot file, must extract the name of an underlining ttf
  583. // file. The file could be on the net so we need try excepts.
  584. //
  585. try
  586. {
  587. if(bVerifyFOT(&fvw,&wrd,pflEmbed,pdwPidTid))
  588. {
  589. // this could except which is why we do it here
  590. vToUnicodeN(awcFile, MAX_PATH, wrd.pszNameTTF, strlen(wrd.pszNameTTF)+1);
  591. Result = FOT_IS_FOT;
  592. }
  593. else
  594. {
  595. Result = FOT_NOT_FOT;
  596. }
  597. }
  598. except(EXCEPTION_EXECUTE_HANDLER)
  599. {
  600. WARNING("bVerifyFOT exception accessing font file\n");
  601. Result = FOT_EXCEPTED;
  602. }
  603. if(Result == FOT_IS_FOT)
  604. {
  605. if (bMakePathNameW(awcPath,awcFile,NULL, pfl))
  606. {
  607. //
  608. // Determine pathname length
  609. //
  610. cNeed = wcslen(awcPath) + 1;
  611. pwszFOT = awcPath;
  612. }
  613. // cGetTTFFromFOT called by font sweeper.
  614. // TTF file might exist over net but connection has not been established yet.
  615. else if (pfl)
  616. {
  617. cNeed = wcslen(awcFile) + 1;
  618. pwszFOT = awcFile;
  619. }
  620. }
  621. else if(Result != FOT_EXCEPTED)
  622. {
  623. //
  624. // We have to assume it is another type of file.
  625. // just copy the name in the buffer
  626. //
  627. cNeed = wcslen(pwszFOT) + 1;
  628. if (pfl)
  629. {
  630. KdPrint(("cGetTTFFromFOT: Invalid FOT file: %ws\n", pwszFOT));
  631. *pfl |= FONT_ISNOT_FOT;
  632. }
  633. }
  634. vUnmapFileClideSide(&fvw);
  635. }
  636. }
  637. else
  638. {
  639. cNeed = cwcFOT + 1;
  640. if (pfl)
  641. {
  642. KdPrint(("cGetTTFFromFOT: Invalid FOT file: %ws\n", pwszFOT));
  643. *pfl |= FONT_ISNOT_FOT;
  644. }
  645. }
  646. if (cNeed == 0)
  647. {
  648. KdPrint(("cGetTTFFromFOT failed for font file %ws\n", pwszFOT));
  649. }
  650. //
  651. // If return buffer exists and we succeded, copy pathname to it.
  652. //
  653. if (cNeed &&
  654. (pwszTTF != (PWSZ) NULL))
  655. {
  656. if (cNeed <= cwcTTF)
  657. {
  658. wcscpy(pwszTTF, pwszFOT);
  659. }
  660. else
  661. {
  662. WARNING("gdisrv!cGetTTFFromFOT(): buffer too small\n");
  663. cNeed = 0;
  664. }
  665. }
  666. else
  667. {
  668. //
  669. // Otherwise, caller just wants us to return the number of characters.
  670. //
  671. }
  672. return cNeed;
  673. }
  674. /******************************Public*Routine******************************\
  675. *
  676. * BOOL bInitSystemAndFontsDirectoriesW(WCHAR **ppwcSystemDir, WCHAR **ppwcFontsDir)
  677. *
  678. * Effects:
  679. *
  680. * Warnings:
  681. *
  682. * History:
  683. * 30-Oct-1995 -by- Bodin Dresevic [BodinD]
  684. * Wrote it.
  685. \**************************************************************************/
  686. WCHAR *gpwcSystemDir = NULL;
  687. WCHAR *gpwcFontsDir = NULL;
  688. #define WSTR_SYSTEM_SUBDIR L"\\system"
  689. #define WSTR_FONT_SUBDIR L"\\fonts"
  690. BOOL bInitSystemAndFontsDirectoriesW(WCHAR **ppwcSystemDir, WCHAR **ppwcFontsDir)
  691. {
  692. WCHAR awcWindowsDir[MAX_PATH];
  693. UINT cwchWinPath, cwchSystem, cwchFonts;
  694. BOOL bRet = TRUE;
  695. // see if already initialized, if yes we are done.
  696. if (!(*ppwcSystemDir))
  697. {
  698. // Compute the windows and font directory pathname lengths (including NULL).
  699. // Note that cwchWinPath may have a trailing '\', in which case we will
  700. // have computed the path length to be one greater than it should be.
  701. cwchWinPath = GetSystemWindowsDirectoryW(awcWindowsDir, MAX_PATH);
  702. if( cwchWinPath ){
  703. // the cwchWinPath value does not include the terminating zero
  704. if (awcWindowsDir[cwchWinPath - 1] == L'\\')
  705. {
  706. cwchWinPath -= 1;
  707. }
  708. awcWindowsDir[cwchWinPath] = L'\0'; // make sure to zero terminate
  709. cwchSystem = cwchWinPath + sizeof(WSTR_SYSTEM_SUBDIR)/sizeof(WCHAR);
  710. cwchFonts = cwchWinPath + sizeof(WSTR_FONT_SUBDIR)/sizeof(WCHAR);
  711. if (*ppwcSystemDir = LocalAlloc(LMEM_FIXED, (cwchSystem+cwchFonts) * sizeof(WCHAR)))
  712. {
  713. *ppwcFontsDir = &((*ppwcSystemDir)[cwchSystem]);
  714. wcscpy(*ppwcSystemDir,awcWindowsDir);
  715. wcscpy(*ppwcFontsDir,awcWindowsDir);
  716. // Append the system and font subdirectories
  717. lstrcatW(*ppwcSystemDir, WSTR_SYSTEM_SUBDIR);
  718. lstrcatW(*ppwcFontsDir, WSTR_FONT_SUBDIR);
  719. }
  720. else
  721. {
  722. bRet = FALSE;
  723. }
  724. }
  725. else
  726. {
  727. bRet = FALSE;
  728. }
  729. }
  730. return bRet;
  731. }
  732. /******************************Public*Routine******************************\
  733. * vConverLogFont *
  734. * *
  735. * Converts a LOGFONTA into an equivalent ENUMLOGFONTEXDVW structure. *
  736. * *
  737. * History: *
  738. * Thu 15-Aug-1991 13:01:33 by Kirk Olynyk [kirko] *
  739. * Wrote it. *
  740. \**************************************************************************/
  741. VOID vConvertLogFont(
  742. ENUMLOGFONTEXDVW *pelfexdvw,
  743. LOGFONTA *plf
  744. )
  745. {
  746. ENUMLOGFONTEXW *pelfw = &pelfexdvw->elfEnumLogfontEx;
  747. ULONG cchMax;
  748. // this one does everyting but the lfFaceName;
  749. vConvertLogicalFont(pelfexdvw,plf);
  750. // do lfFaceName
  751. cchMax = cchCutOffStrLen((PSZ) plf->lfFaceName, LF_FACESIZE);
  752. RtlZeroMemory(pelfw->elfLogFont.lfFaceName , LF_FACESIZE * sizeof(WCHAR) );
  753. // translate the face name
  754. vToUnicodeN((LPWSTR) pelfw->elfLogFont.lfFaceName,
  755. cchMax,
  756. (LPSTR) plf->lfFaceName,
  757. cchMax);
  758. if (cchMax == LF_FACESIZE)
  759. pelfw->elfLogFont.lfFaceName[LF_FACESIZE - 1] = L'\0'; // truncate so NULL will fit
  760. else
  761. pelfw->elfLogFont.lfFaceName[cchMax] = L'\0';
  762. }
  763. /******************************Public*Routine******************************\
  764. * vConvertLogFontW *
  765. * *
  766. * Converts a LOGFONTW to an ENUMLOGFONTEXDVW *
  767. * *
  768. * History: *
  769. * Fri 16-Aug-1991 14:02:05 by Kirk Olynyk [kirko] *
  770. * Wrote it. *
  771. \**************************************************************************/
  772. VOID
  773. vConvertLogFontW(
  774. ENUMLOGFONTEXDVW *pelfw,
  775. LOGFONTW *plfw
  776. )
  777. {
  778. // this one does everything except for lfFaceName
  779. vConvertLogicalFont(pelfw,plfw);
  780. // do lfFaceName
  781. RtlCopyMemory(
  782. pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName,
  783. plfw->lfFaceName,
  784. LF_FACESIZE * sizeof(WCHAR)
  785. );
  786. }
  787. /******************************Public*Routine******************************\
  788. * vConvertLogicalFont *
  789. * *
  790. * Simply copies over all of the fields of a LOGFONTA or LOGFONTW *
  791. * to the fields of a target ENUMLOGFONTEXDVW. The only exception is *
  792. * the FaceName which must be dealt with by another routine. *
  793. * *
  794. * History: *
  795. * Fri 16-Aug-1991 14:02:14 by Kirk Olynyk [kirko] *
  796. * Wrote it. *
  797. \**************************************************************************/
  798. static
  799. VOID vConvertLogicalFont(
  800. ENUMLOGFONTEXDVW *pelfw,
  801. PVOID pv
  802. )
  803. {
  804. pelfw->elfEnumLogfontEx.elfLogFont.lfHeight = ((LOGFONTA*)pv)->lfHeight;
  805. pelfw->elfEnumLogfontEx.elfLogFont.lfWidth = ((LOGFONTA*)pv)->lfWidth;
  806. pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement = ((LOGFONTA*)pv)->lfEscapement;
  807. pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation = ((LOGFONTA*)pv)->lfOrientation;
  808. pelfw->elfEnumLogfontEx.elfLogFont.lfWeight = ((LOGFONTA*)pv)->lfWeight;
  809. pelfw->elfEnumLogfontEx.elfLogFont.lfItalic = ((LOGFONTA*)pv)->lfItalic;
  810. pelfw->elfEnumLogfontEx.elfLogFont.lfUnderline = ((LOGFONTA*)pv)->lfUnderline;
  811. pelfw->elfEnumLogfontEx.elfLogFont.lfStrikeOut = ((LOGFONTA*)pv)->lfStrikeOut;
  812. pelfw->elfEnumLogfontEx.elfLogFont.lfCharSet = ((LOGFONTA*)pv)->lfCharSet;
  813. pelfw->elfEnumLogfontEx.elfLogFont.lfOutPrecision = ((LOGFONTA*)pv)->lfOutPrecision;
  814. pelfw->elfEnumLogfontEx.elfLogFont.lfClipPrecision = ((LOGFONTA*)pv)->lfClipPrecision;
  815. pelfw->elfEnumLogfontEx.elfLogFont.lfQuality = ((LOGFONTA*)pv)->lfQuality;
  816. pelfw->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily = ((LOGFONTA*)pv)->lfPitchAndFamily;
  817. // lfFaceName is done in the calling routine
  818. pelfw->elfEnumLogfontEx.elfFullName[0] = 0;
  819. pelfw->elfEnumLogfontEx.elfStyle[0] = 0;
  820. pelfw->elfEnumLogfontEx.elfScript[0] = 0;
  821. pelfw->elfDesignVector.dvReserved = STAMP_DESIGNVECTOR;
  822. pelfw->elfDesignVector.dvNumAxes = 0;
  823. }
  824. /******************************Public*Routine******************************\
  825. *
  826. * BOOL bConvertLogFontWToLogFontA(LOGFONTA *plfw, LOGFONTW *plfa)
  827. *
  828. * History:
  829. * 10-Dec-1996 -by- Bodin Dresevic [BodinD]
  830. * Wrote it.
  831. \**************************************************************************/
  832. BOOL bConvertLogFontWToLogFontA(LOGFONTA *plfa, LOGFONTW *plfw)
  833. {
  834. ULONG cchMax;
  835. plfa->lfHeight = plfw->lfHeight ;
  836. plfa->lfWidth = plfw->lfWidth ;
  837. plfa->lfEscapement = plfw->lfEscapement ;
  838. plfa->lfOrientation = plfw->lfOrientation ;
  839. plfa->lfWeight = plfw->lfWeight ;
  840. plfa->lfItalic = plfw->lfItalic ;
  841. plfa->lfUnderline = plfw->lfUnderline ;
  842. plfa->lfStrikeOut = plfw->lfStrikeOut ;
  843. plfa->lfCharSet = plfw->lfCharSet ;
  844. plfa->lfOutPrecision = plfw->lfOutPrecision ;
  845. plfa->lfClipPrecision = plfw->lfClipPrecision ;
  846. plfa->lfQuality = plfw->lfQuality ;
  847. plfa->lfPitchAndFamily = plfw->lfPitchAndFamily ;
  848. cchMax = cwcCutOffStrLen(plfw->lfFaceName, LF_FACESIZE);
  849. return (bToASCII_N(plfa->lfFaceName, LF_FACESIZE,
  850. plfw->lfFaceName, cchMax));
  851. }
  852. /******************************Public*Routine******************************\
  853. * bConvertEnumLogFontExWToEnumLogFontExA *
  854. * *
  855. * Simply copies over all of the fields of ENUMLOGFONTEXDVW *
  856. * to the fields of a target ENUMLOGFONTEXDVA. It is all wrapped up here *
  857. * because the ENUMLOGFONTEXDV may move around a bit. This makes *
  858. * using MOVEMEM a little tricky. *
  859. * *
  860. * History: *
  861. * Fri 16-Aug-1991 14:02:14 by Kirk Olynyk [kirko] *
  862. * Wrote it. *
  863. \**************************************************************************/
  864. BOOL bConvertEnumLogFontExWToEnumLogFontExA(ENUMLOGFONTEXA *pelfexa,ENUMLOGFONTEXW *pelfexw)
  865. {
  866. ULONG cchMax;
  867. if (!bConvertLogFontWToLogFontA(&pelfexa->elfLogFont,
  868. &pelfexw->elfLogFont))
  869. {
  870. // conversion to ascii failed, return error
  871. WARNING("bConvertLogFontWToLogFontA failed\n");
  872. return(FALSE);
  873. }
  874. cchMax = cwcCutOffStrLen(pelfexw->elfFullName, LF_FULLFACESIZE);
  875. if(!bToASCII_N(pelfexa->elfFullName, LF_FULLFACESIZE,
  876. pelfexw->elfFullName, cchMax
  877. ))
  878. {
  879. // conversion to ascii failed, return error
  880. WARNING("bConvertEnumLogFontExWToEnumLogFontExA: bToASCII failed\n");
  881. return(FALSE);
  882. }
  883. pelfexa->elfFullName[LF_FULLFACESIZE-1]=0; // zero terminate
  884. cchMax = cwcCutOffStrLen(pelfexw->elfStyle, LF_FACESIZE);
  885. if(!bToASCII_N(pelfexa->elfStyle, LF_FACESIZE,
  886. pelfexw->elfStyle, cchMax))
  887. {
  888. // conversion to ascii failed, return error
  889. WARNING("bConvertEnumLogFontExWToEnumLogFontExA: bToASCII failed\n");
  890. return(FALSE);
  891. }
  892. cchMax = cwcCutOffStrLen(pelfexw->elfScript, LF_FACESIZE);
  893. if(!bToASCII_N(pelfexa->elfScript, LF_FACESIZE,
  894. pelfexw->elfScript, cchMax
  895. ))
  896. {
  897. // conversion to ascii failed, return error
  898. WARNING("bConvertEnumLogFontExWToEnumLogFontExA: bToASCII_N failed\n");
  899. return(FALSE);
  900. }
  901. return (TRUE);
  902. }
  903. /******************************Public*Routine******************************\
  904. * bConvertEnumLogFontExDv_AtoW *
  905. * *
  906. * Simply copies over all of the fields of ENUMLOGFONTEXDVW *
  907. * to the fields of a target ENUMLOGFONTEXDV. It is all wrapped up here *
  908. * because the fields may move around a bit. This make *
  909. * using MOVEMEM a little tricky. *
  910. * *
  911. * History: *
  912. * Fri 16-Aug-1991 14:02:14 by Kirk Olynyk [kirko] *
  913. * Wrote it. *
  914. \**************************************************************************/
  915. VOID vConvertEnumLogFontExDvAtoW(
  916. ENUMLOGFONTEXDVW *pelfw,
  917. ENUMLOGFONTEXDVA *pelfa
  918. )
  919. {
  920. ULONG cchMax;
  921. pelfw->elfEnumLogfontEx.elfLogFont.lfHeight = pelfa->elfEnumLogfontEx.elfLogFont.lfHeight ;
  922. pelfw->elfEnumLogfontEx.elfLogFont.lfWidth = pelfa->elfEnumLogfontEx.elfLogFont.lfWidth ;
  923. pelfw->elfEnumLogfontEx.elfLogFont.lfEscapement = pelfa->elfEnumLogfontEx.elfLogFont.lfEscapement ;
  924. pelfw->elfEnumLogfontEx.elfLogFont.lfOrientation = pelfa->elfEnumLogfontEx.elfLogFont.lfOrientation ;
  925. pelfw->elfEnumLogfontEx.elfLogFont.lfWeight = pelfa->elfEnumLogfontEx.elfLogFont.lfWeight ;
  926. pelfw->elfEnumLogfontEx.elfLogFont.lfItalic = pelfa->elfEnumLogfontEx.elfLogFont.lfItalic ;
  927. pelfw->elfEnumLogfontEx.elfLogFont.lfUnderline = pelfa->elfEnumLogfontEx.elfLogFont.lfUnderline ;
  928. pelfw->elfEnumLogfontEx.elfLogFont.lfStrikeOut = pelfa->elfEnumLogfontEx.elfLogFont.lfStrikeOut ;
  929. pelfw->elfEnumLogfontEx.elfLogFont.lfCharSet = pelfa->elfEnumLogfontEx.elfLogFont.lfCharSet ;
  930. pelfw->elfEnumLogfontEx.elfLogFont.lfOutPrecision = pelfa->elfEnumLogfontEx.elfLogFont.lfOutPrecision ;
  931. pelfw->elfEnumLogfontEx.elfLogFont.lfClipPrecision = pelfa->elfEnumLogfontEx.elfLogFont.lfClipPrecision ;
  932. pelfw->elfEnumLogfontEx.elfLogFont.lfQuality = pelfa->elfEnumLogfontEx.elfLogFont.lfQuality ;
  933. pelfw->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily = pelfa->elfEnumLogfontEx.elfLogFont.lfPitchAndFamily ;
  934. RtlZeroMemory( pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName , LF_FACESIZE * sizeof(WCHAR) );
  935. cchMax = cchCutOffStrLen((PSZ)pelfa->elfEnumLogfontEx.elfLogFont.lfFaceName, LF_FACESIZE);
  936. vToUnicodeN (
  937. pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName, cchMax,
  938. pelfa->elfEnumLogfontEx.elfLogFont.lfFaceName, cchMax
  939. );
  940. if (cchMax == LF_FACESIZE)
  941. {
  942. // truncate so NULL will fit
  943. pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName[LF_FACESIZE - 1] = L'\0';
  944. }
  945. else
  946. {
  947. pelfw->elfEnumLogfontEx.elfLogFont.lfFaceName[cchMax] = L'\0';
  948. }
  949. RtlZeroMemory( pelfw->elfEnumLogfontEx.elfFullName , LF_FACESIZE * sizeof(WCHAR) );
  950. cchMax = cchCutOffStrLen((PSZ)pelfa->elfEnumLogfontEx.elfFullName, LF_FULLFACESIZE);
  951. vToUnicodeN (
  952. pelfw->elfEnumLogfontEx.elfFullName, cchMax,
  953. pelfa->elfEnumLogfontEx.elfFullName, cchMax
  954. );
  955. if (cchMax == LF_FULLFACESIZE)
  956. {
  957. // truncate so NULL will fit
  958. pelfw->elfEnumLogfontEx.elfFullName[LF_FULLFACESIZE - 1] = L'\0';
  959. }
  960. else
  961. {
  962. pelfw->elfEnumLogfontEx.elfFullName[cchMax] = L'\0';
  963. }
  964. RtlZeroMemory( pelfw->elfEnumLogfontEx.elfStyle , LF_FACESIZE * sizeof(WCHAR) );
  965. cchMax = cchCutOffStrLen((PSZ)pelfa->elfEnumLogfontEx.elfStyle, LF_FACESIZE);
  966. vToUnicodeN (
  967. pelfw->elfEnumLogfontEx.elfStyle, cchMax,
  968. pelfa->elfEnumLogfontEx.elfStyle, cchMax
  969. );
  970. if (cchMax == LF_FACESIZE)
  971. {
  972. // truncate so NULL will fit
  973. pelfw->elfEnumLogfontEx.elfStyle[LF_FACESIZE - 1] = L'\0';
  974. }
  975. else
  976. {
  977. pelfw->elfEnumLogfontEx.elfStyle[cchMax] = L'\0';
  978. }
  979. RtlZeroMemory( pelfw->elfEnumLogfontEx.elfScript , LF_FACESIZE * sizeof(WCHAR) );
  980. cchMax = cchCutOffStrLen((PSZ)pelfa->elfEnumLogfontEx.elfScript, LF_FACESIZE);
  981. vToUnicodeN (
  982. pelfw->elfEnumLogfontEx.elfScript, cchMax,
  983. pelfa->elfEnumLogfontEx.elfScript, cchMax
  984. );
  985. if (cchMax == LF_FACESIZE)
  986. {
  987. // truncate so NULL will fit
  988. pelfw->elfEnumLogfontEx.elfScript[LF_FACESIZE - 1] = L'\0';
  989. }
  990. else
  991. {
  992. pelfw->elfEnumLogfontEx.elfScript[cchMax] = L'\0';
  993. }
  994. // copy minimal amount of stuff from design vector
  995. RtlCopyMemory(&pelfw->elfDesignVector,
  996. &pelfa->elfDesignVector,
  997. SIZEOFDV(pelfa->elfDesignVector.dvNumAxes));
  998. }
  999. /******************************Public*Routine******************************\
  1000. * ulEnumFontsOpen
  1001. *
  1002. * History:
  1003. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  1004. * Wrote it.
  1005. \**************************************************************************/
  1006. ULONG_PTR ulEnumFontsOpen (
  1007. HDC hdc,
  1008. LPWSTR pwszFaceName,
  1009. ULONG lfCharSet,
  1010. ULONG iEnumType, // enumfonts, enumfontfamilies or enumfontfamiliesex
  1011. FLONG flWin31Compat,
  1012. ULONG *pulCount
  1013. )
  1014. {
  1015. ULONG cwchFaceName;
  1016. ULONG cjData;
  1017. cwchFaceName = (pwszFaceName != (PWSZ) NULL) ? (wcslen(pwszFaceName) + 1) : 0;
  1018. return NtGdiEnumFontOpen(hdc,iEnumType,flWin31Compat,
  1019. cwchFaceName,pwszFaceName, lfCharSet,pulCount);
  1020. }
  1021. /******************************Public*Routine******************************\
  1022. * vEnumFontsClose
  1023. *
  1024. * History:
  1025. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  1026. * Wrote it.
  1027. \**************************************************************************/
  1028. VOID vEnumFontsClose (ULONG_PTR ulEnumHandle)
  1029. {
  1030. NtGdiEnumFontClose(ulEnumHandle);
  1031. }
  1032. /******************************Public*Routine******************************\
  1033. *
  1034. * vConvertAxesListW2AxesListA
  1035. *
  1036. *
  1037. * History:
  1038. * 18-Nov-1996 -by- Bodin Dresevic [BodinD]
  1039. * Wrote it.
  1040. \**************************************************************************/
  1041. VOID vConvertAxesListW2AxesListA(AXESLISTA *paxlA, AXESLISTW *paxlW)
  1042. {
  1043. ULONG iAxis = 0;
  1044. paxlA->axlReserved = paxlW->axlReserved;
  1045. paxlA->axlNumAxes = paxlW->axlNumAxes;
  1046. for (iAxis = 0; iAxis < paxlW->axlNumAxes; iAxis ++)
  1047. {
  1048. ULONG cch;
  1049. paxlA->axlAxisInfo[iAxis].axMinValue = paxlW->axlAxisInfo[iAxis].axMinValue;
  1050. paxlA->axlAxisInfo[iAxis].axMaxValue = paxlW->axlAxisInfo[iAxis].axMaxValue;
  1051. cch = cwcCutOffStrLen(paxlW->axlAxisInfo[iAxis].axAxisName,
  1052. MM_MAX_AXES_NAMELEN);
  1053. bToASCII_N(paxlA->axlAxisInfo[iAxis].axAxisName, MM_MAX_AXES_NAMELEN,
  1054. paxlW->axlAxisInfo[iAxis].axAxisName, cch);
  1055. }
  1056. }
  1057. /******************************Public*Routine******************************\
  1058. *
  1059. * int iAnsiCallback (
  1060. *
  1061. * History:
  1062. * 28-Jan-1993 -by- Bodin Dresevic [BodinD]
  1063. * Wrote it.
  1064. \**************************************************************************/
  1065. int iAnsiCallback (
  1066. ENUMFONTDATAW *pefdw,
  1067. ULONG iEnumType,
  1068. FONTENUMPROCA lpFontFunc,
  1069. LPARAM lParam
  1070. )
  1071. {
  1072. // full size structures with MAX_MM_AXES arrays
  1073. // on the stack, probably bigger then needed.
  1074. ENUMLOGFONTEXDVA elfexa ;
  1075. ENUMTEXTMETRICA ntma;
  1076. NTMW_INTERNAL *pntmi = (NTMW_INTERNAL *)((BYTE*)pefdw + pefdw->dpNtmi);
  1077. DESIGNVECTOR *pdvSrc = &(pefdw->elfexw.elfDesignVector);
  1078. // copy out design vector
  1079. RtlCopyMemory(&elfexa.elfDesignVector, pdvSrc, SIZEOFDV(pdvSrc->dvNumAxes));
  1080. // convert AXESLIST to ansi
  1081. vConvertAxesListW2AxesListA(&ntma.etmAxesList, &pntmi->entmw.etmAxesList);
  1082. // Convert ENUMLOGFONTEX
  1083. if (!bConvertEnumLogFontExWToEnumLogFontExA(&elfexa.elfEnumLogfontEx, &pefdw->elfexw.elfEnumLogfontEx))
  1084. {
  1085. WARNING("gdi32!EFCallbackWtoA(): ENUMLOGFONT conversion failed\n");
  1086. return 0;
  1087. }
  1088. // Convert NEWTEXTMETRIC.
  1089. vNewTextMetricExWToNewTextMetricExA(&ntma.etmNewTextMetricEx, pntmi);
  1090. return lpFontFunc(
  1091. (LOGFONTA *)&elfexa,
  1092. (TEXTMETRICA *)&ntma,
  1093. pefdw->flType,
  1094. lParam
  1095. );
  1096. }
  1097. /******************************Public*Routine******************************\
  1098. * iScaleEnum
  1099. *
  1100. * The Win95 Universal printer driver (UNIDRV) has scalable fonts, but does
  1101. * not set the scalable capability flags in TEXTCAPS. Instead, it enumerates
  1102. * back scalable printer fonts at several different (fixed) point sizes.
  1103. *
  1104. * We support this by detecting, on the server-side, when we are enumerating
  1105. * a scalable printer and setting the ENUMFONT_SCALE_HACK flag in the flType
  1106. * field of the ENUMFONTDATAW structure.
  1107. *
  1108. * For more details, refer to the Win95 sources found on \\tal\msdos in
  1109. * \src\win\drivers\printer\universa\unidrv\enumobj.c. Specifically, the
  1110. * function of interest is UniEnumDFonts().
  1111. *
  1112. * Returns:
  1113. * Value returned by callback if successful, 0 otherwise.
  1114. *
  1115. * History:
  1116. * 08-Jan-1996 -by- Gilman Wong [gilmanw]
  1117. * Wrote it.
  1118. \**************************************************************************/
  1119. #define EFI_UNICODE 1
  1120. CONST int giEnumPointList[] =
  1121. {6, 8, 10, 11, 12, 14, 18, 24, 30, 36, 48};
  1122. int iScaleEnum(
  1123. HDC hdc,
  1124. FONTENUMPROCW lpFontFunc,
  1125. ENUMFONTDATAW *pefd,
  1126. LPARAM lParam,
  1127. ULONG iEnumType,
  1128. FLONG fl
  1129. )
  1130. {
  1131. int i, cPointSizes = sizeof(giEnumPointList) / sizeof(int);
  1132. int iHeight;
  1133. int iXdpi, iYdpi;
  1134. int iRet;
  1135. // make the structure on the stack is DWORD aligned
  1136. DWORD efd[CJ_EFDW0/sizeof(DWORD)];
  1137. ENUMFONTDATAW *pefdLocal = (ENUMFONTDATAW *)efd;
  1138. iXdpi = GetDeviceCaps(hdc, LOGPIXELSX);
  1139. iYdpi = GetDeviceCaps(hdc, LOGPIXELSY);
  1140. for (i = 0; i < cPointSizes; i++)
  1141. {
  1142. // this has to be true because for these device fonts no
  1143. // extra mm data will ever be needed, only logfont and ntmi
  1144. NTMW_INTERNAL *pntmi, *pntmiDef;
  1145. TEXTMETRICW *ptmw, *ptmwDef;
  1146. LOGFONTW *plfw, *plfwDef;
  1147. ASSERTGDI(pefd->cjEfdw <= sizeof(efd), "iScaleEnum size problem\n");
  1148. RtlCopyMemory(pefdLocal, pefd, pefd->cjEfdw);
  1149. pntmi = (NTMW_INTERNAL *)((BYTE*)pefdLocal + pefdLocal->dpNtmi);
  1150. pntmiDef = (NTMW_INTERNAL *)((BYTE*)pefd + pefd->dpNtmi);
  1151. ptmw = (TEXTMETRICW *) &pntmi->entmw.etmNewTextMetricEx;
  1152. ptmwDef = (TEXTMETRICW *) &pntmiDef->entmw.etmNewTextMetricEx;
  1153. plfw = (LOGFONTW *) &pefdLocal->elfexw;
  1154. plfwDef = (LOGFONTW *) &pefd->elfexw;
  1155. // Scale TEXTMETRIC to match enumerated height.
  1156. iHeight = MulDiv(giEnumPointList[i], iYdpi, 72);
  1157. ptmw->tmHeight = iHeight;
  1158. ptmw->tmAscent = MulDiv(ptmwDef->tmAscent, iHeight, ptmwDef->tmHeight);
  1159. ptmw->tmInternalLeading = MulDiv(ptmwDef->tmInternalLeading, iHeight,
  1160. ptmwDef->tmHeight);
  1161. ptmw->tmExternalLeading = MulDiv(ptmwDef->tmExternalLeading, iHeight,
  1162. ptmwDef->tmHeight);
  1163. ptmw->tmAveCharWidth = MulDiv(ptmwDef->tmAveCharWidth, iHeight,
  1164. ptmwDef->tmHeight);
  1165. ptmw->tmMaxCharWidth = MulDiv(ptmwDef->tmMaxCharWidth, iHeight,
  1166. ptmwDef->tmHeight);
  1167. // Scale LOGFONT to match enumerated height.
  1168. plfw->lfHeight = MulDiv(plfwDef->lfHeight, iHeight, ptmwDef->tmHeight);
  1169. plfw->lfWidth = MulDiv(plfwDef->lfWidth, iHeight, ptmwDef->tmHeight);
  1170. // Invoke the callback function.
  1171. if (fl & EFI_UNICODE)
  1172. {
  1173. iRet = lpFontFunc(
  1174. (LOGFONTW *) plfw,
  1175. (TEXTMETRICW *) ptmw,
  1176. pefd->flType,
  1177. lParam );
  1178. }
  1179. else
  1180. {
  1181. iRet = iAnsiCallback (pefdLocal,
  1182. iEnumType,
  1183. (FONTENUMPROCA)lpFontFunc,
  1184. lParam);
  1185. }
  1186. // Break out early if callback returned error.
  1187. if (!iRet)
  1188. break;
  1189. }
  1190. return iRet;
  1191. }
  1192. /******************************Public*Routine******************************\
  1193. * EnumFontsInternalW
  1194. *
  1195. * History:
  1196. * Mon 17-Aug-1998 -by- Bodin Dresevic [BodinD]
  1197. * update: since 1992 this function was rewritten quite a few times
  1198. *
  1199. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  1200. * Wrote it.
  1201. \**************************************************************************/
  1202. int WINAPI EnumFontsInternalW (
  1203. HDC hdc, // enumerate for this device
  1204. LPCWSTR pwszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1205. ULONG lfCharSet, // only used with EnumFontFamiliesEx,
  1206. FONTENUMPROCW lpFontFunc, // callback
  1207. LPARAM lParam, // user defined data
  1208. ULONG iEnumType, // who is calling....
  1209. FLONG fl
  1210. )
  1211. {
  1212. BOOL bMore; // set TRUE if more data to process
  1213. ULONG_PTR ulEnumID; // server side font enumeration handle
  1214. int iRet = 1; // return value from callback
  1215. ULONG cjEfdw; // capacity of memory data window
  1216. ULONG cjEfdwRet; // size of data returned
  1217. PENUMFONTDATAW pefdw; // font enumeration data buffer
  1218. PENUMFONTDATAW pefdwScan; // use to parse data buffer
  1219. PENUMFONTDATAW pefdwEnd; // limit of data buffer
  1220. FLONG flWin31Compat; // Win3.1 app hack backward compatibility flags
  1221. // Get the compatibility flags.
  1222. flWin31Compat = (FLONG) GetAppCompatFlags(NULL);
  1223. // Open a font enumeration. The font enumeration is uniquely identified
  1224. // by the identifier returned by ulEnumFontOpen().
  1225. ulEnumID = ulEnumFontsOpen(
  1226. hdc, (LPWSTR)pwszFaceName, lfCharSet,
  1227. iEnumType, flWin31Compat, &cjEfdw);
  1228. if (!ulEnumID)
  1229. {
  1230. GdiSetLastError(ERROR_INVALID_HANDLE);
  1231. return 0;
  1232. }
  1233. if (cjEfdw == 0)
  1234. {
  1235. vEnumFontsClose(ulEnumID);
  1236. return iRet;
  1237. }
  1238. // alloc memory
  1239. if (!(pefdw = (PENUMFONTDATAW) LOCALALLOC(cjEfdw)))
  1240. {
  1241. WARNING("gdi32!EnumFontsInternalW(): could not allocate memory for enumeration\n");
  1242. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1243. vEnumFontsClose(ulEnumID);
  1244. return 0;
  1245. }
  1246. if (NtGdiEnumFontChunk(hdc,ulEnumID,cjEfdw,&cjEfdwRet,pefdw))
  1247. {
  1248. // Scan through the data buffer.
  1249. ASSERTGDI(cjEfdwRet <= cjEfdw, "NtGdiEnumFontChunk problem\n");
  1250. pefdwScan = pefdw;
  1251. pefdwEnd = (ENUMFONTDATAW *)((BYTE *)pefdw + cjEfdwRet);
  1252. while (pefdwScan < pefdwEnd)
  1253. {
  1254. // GACF_ENUMTTNOTDEVICE backward compatibility hack.
  1255. // If this flag is set, we need to mask out the DEVICE_FONTTYPE
  1256. // if this is a TrueType font.
  1257. if ( (flWin31Compat & GACF_ENUMTTNOTDEVICE)
  1258. && (pefdwScan->flType & TRUETYPE_FONTTYPE) )
  1259. pefdwScan->flType &= ~DEVICE_FONTTYPE;
  1260. // The Win95 UNIDRV printer driver enumerates scalable fonts at
  1261. // several different sizes. The server sets the ENUMFONT_SCALE_HACK
  1262. // flag if we need to emulate that behavior.
  1263. if ( pwszFaceName && (pefdwScan->flType & ENUMFONT_SCALE_HACK))
  1264. {
  1265. // Clear the hack flag before calling. Caller doesn't need to
  1266. // see this (internal use only) flag.
  1267. pefdwScan->flType &= ~ENUMFONT_SCALE_HACK;
  1268. iRet = iScaleEnum(hdc, lpFontFunc, pefdwScan, lParam,
  1269. iEnumType, fl);
  1270. }
  1271. else
  1272. {
  1273. // Do the callback with data pointed to by pefdwScan.
  1274. if (fl & EFI_UNICODE)
  1275. {
  1276. NTMW_INTERNAL *pntmi =
  1277. (NTMW_INTERNAL *)((BYTE*)pefdwScan + pefdwScan->dpNtmi);
  1278. iRet = lpFontFunc(
  1279. (LOGFONTW *)&pefdwScan->elfexw,
  1280. (TEXTMETRICW *)&pntmi->entmw,
  1281. pefdwScan->flType,
  1282. lParam );
  1283. }
  1284. else
  1285. {
  1286. iRet = iAnsiCallback (pefdwScan,
  1287. iEnumType,
  1288. (FONTENUMPROCA)lpFontFunc,
  1289. lParam);
  1290. }
  1291. }
  1292. // Break out of for-loop if callback returned 0.
  1293. if (!iRet)
  1294. {
  1295. break;
  1296. }
  1297. // Next ENUMFONTDATAW.
  1298. pefdwScan = (ENUMFONTDATAW *)((BYTE *)pefdwScan + pefdwScan->cjEfdw);
  1299. }
  1300. }
  1301. // Deallocate font enumeration data.
  1302. LOCALFREE(pefdw);
  1303. // Remember to close the font enumeration handle.
  1304. vEnumFontsClose(ulEnumID);
  1305. // Leave.
  1306. return iRet;
  1307. }
  1308. /******************************Public*Routine******************************\
  1309. * EnumFontsW
  1310. *
  1311. * History:
  1312. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  1313. * Wrote it.
  1314. \**************************************************************************/
  1315. int WINAPI EnumFontsW
  1316. (
  1317. HDC hdc, // enumerate for this device
  1318. LPCWSTR pwszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1319. FONTENUMPROCW lpFontFunc, // callback
  1320. LPARAM lParam // user defined data
  1321. )
  1322. {
  1323. FIXUP_HANDLE(hdc);
  1324. return EnumFontsInternalW(
  1325. hdc,
  1326. pwszFaceName,
  1327. DEFAULT_CHARSET,
  1328. lpFontFunc,
  1329. lParam,
  1330. TYPE_ENUMFONTS,
  1331. EFI_UNICODE
  1332. );
  1333. }
  1334. /******************************Public*Routine******************************\
  1335. * EnumFontFamiliesW
  1336. *
  1337. * History:
  1338. * 08-Aug-1992 -by- Gilman Wong [gilmanw]
  1339. * Wrote it.
  1340. \**************************************************************************/
  1341. int WINAPI EnumFontFamiliesW
  1342. (
  1343. HDC hdc, // enumerate for this device
  1344. LPCWSTR pwszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1345. FONTENUMPROCW lpFontFunc, // callback
  1346. LPARAM lParam // user defined data
  1347. )
  1348. {
  1349. FIXUP_HANDLE(hdc);
  1350. return EnumFontsInternalW(
  1351. hdc,
  1352. pwszFaceName,
  1353. DEFAULT_CHARSET,
  1354. lpFontFunc,
  1355. lParam,
  1356. TYPE_ENUMFONTFAMILIES,
  1357. EFI_UNICODE
  1358. );
  1359. }
  1360. /******************************Public*Routine******************************\
  1361. * EnumFontFamiliesExW
  1362. *
  1363. * History:
  1364. *
  1365. * Mon 10-Jul-1995 -by- Bodin Dresevic [BodinD]
  1366. * Wrote it:
  1367. *
  1368. \**************************************************************************/
  1369. int WINAPI EnumFontFamiliesExW
  1370. (
  1371. HDC hdc,
  1372. LPLOGFONTW plf,
  1373. FONTENUMPROCW lpFontFunc,
  1374. LPARAM lParam,
  1375. DWORD dw
  1376. )
  1377. {
  1378. PWSZ pwszFaceName = NULL;
  1379. FIXUP_HANDLE(hdc);
  1380. if (plf && (plf->lfFaceName[0] != L'\0'))
  1381. pwszFaceName = plf->lfFaceName;
  1382. return EnumFontsInternalW(
  1383. hdc,
  1384. pwszFaceName,
  1385. plf ? plf->lfCharSet : DEFAULT_CHARSET,
  1386. lpFontFunc,
  1387. lParam,
  1388. TYPE_ENUMFONTFAMILIESEX,
  1389. EFI_UNICODE
  1390. );
  1391. }
  1392. /******************************Public*Routine******************************\
  1393. *
  1394. * int EnumFontsInternalA
  1395. *
  1396. * History:
  1397. * 28-Jan-1993 -by- Bodin Dresevic [BodinD]
  1398. * Wrote it.
  1399. \**************************************************************************/
  1400. int EnumFontsInternalA
  1401. (
  1402. HDC hdc, // enumerate for this device
  1403. LPCSTR pszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*),
  1404. ULONG lfCharSet,
  1405. FONTENUMPROCA lpFontFunc, // callback
  1406. LPARAM lParam, // user defined data
  1407. ULONG iEnumType
  1408. )
  1409. {
  1410. PWSZ pwszFaceName;
  1411. int iRet;
  1412. ULONG cchFaceName;
  1413. // If a string was passed in, we need to convert it to UNICODE.
  1414. if ( pszFaceName != (PSZ) NULL )
  1415. {
  1416. // Allocate memory for Unicode string.
  1417. cchFaceName = lstrlenA(pszFaceName) + 1;
  1418. if ( (pwszFaceName = (PWSZ) LOCALALLOC(cchFaceName * sizeof(WCHAR))) == (PWSZ) NULL )
  1419. {
  1420. WARNING("gdi32!EnumFontsA(): could not allocate memory for Unicode string\n");
  1421. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1422. return 0;
  1423. }
  1424. // Convert string to Unicode.
  1425. vToUnicodeN (
  1426. pwszFaceName,
  1427. cchFaceName,
  1428. pszFaceName,
  1429. cchFaceName
  1430. );
  1431. }
  1432. // Otherwise, keep it NULL.
  1433. else
  1434. {
  1435. pwszFaceName = (PWSZ) NULL;
  1436. }
  1437. // Call Unicode version.
  1438. iRet = EnumFontsInternalW(
  1439. hdc,
  1440. pwszFaceName,
  1441. lfCharSet,
  1442. (FONTENUMPROCW)lpFontFunc,
  1443. lParam,
  1444. iEnumType,
  1445. 0 // not unicode
  1446. );
  1447. // Release Unicode string buffer.
  1448. if ( pwszFaceName != (PWSZ) NULL )
  1449. {
  1450. LOCALFREE(pwszFaceName);
  1451. }
  1452. return iRet;
  1453. }
  1454. /******************************Public*Routine******************************\
  1455. *
  1456. * int WINAPI EnumFontsA
  1457. *
  1458. *
  1459. * History:
  1460. * 28-Jan-1993 -by- Bodin Dresevic [BodinD]
  1461. * Wrote it.
  1462. \**************************************************************************/
  1463. int WINAPI EnumFontsA
  1464. (
  1465. HDC hdc, // enumerate for this device
  1466. LPCSTR pszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1467. FONTENUMPROCA lpFontFunc, // callback
  1468. LPARAM lParam // user defined data
  1469. )
  1470. {
  1471. FIXUP_HANDLE(hdc);
  1472. return EnumFontsInternalA (
  1473. hdc,
  1474. pszFaceName,
  1475. DEFAULT_CHARSET,
  1476. lpFontFunc,
  1477. lParam,
  1478. TYPE_ENUMFONTS
  1479. );
  1480. }
  1481. /******************************Public*Routine******************************\
  1482. * EnumFontFamiliesA
  1483. *
  1484. * History:
  1485. * 28-Jan-1993 -by- Bodin Dresevic [BodinD]
  1486. * Wrote it.
  1487. \**************************************************************************/
  1488. int WINAPI EnumFontFamiliesA
  1489. (
  1490. HDC hdc, // enumerate for this device
  1491. LPCSTR pszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1492. FONTENUMPROCA lpFontFunc, // callback
  1493. LPARAM lParam // user defined data
  1494. )
  1495. {
  1496. return EnumFontsInternalA (
  1497. hdc, // enumerate for this device
  1498. pszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1499. DEFAULT_CHARSET,
  1500. lpFontFunc, // callback
  1501. lParam, // user defined data
  1502. TYPE_ENUMFONTFAMILIES
  1503. );
  1504. }
  1505. /******************************Public*Routine******************************\
  1506. * EnumFontFamiliesExA
  1507. *
  1508. * History:
  1509. *
  1510. * Mon 10-Jul-1995 -by- Bodin Dresevic [BodinD]
  1511. * Wrote it:
  1512. *
  1513. \**************************************************************************/
  1514. int WINAPI EnumFontFamiliesExA
  1515. (
  1516. HDC hdc,
  1517. LPLOGFONTA plf,
  1518. FONTENUMPROCA lpFontFunc,
  1519. LPARAM lParam,
  1520. DWORD dw
  1521. )
  1522. {
  1523. LPSTR pszFaceName = NULL;
  1524. FIXUP_HANDLE(hdc);
  1525. if (plf && (plf->lfFaceName[0] != '\0'))
  1526. pszFaceName = plf->lfFaceName;
  1527. return EnumFontsInternalA (
  1528. hdc, // enumerate for this device
  1529. pszFaceName, // use this family name (but Windows erroneously calls in face name *sigh*)
  1530. plf ? plf->lfCharSet : DEFAULT_CHARSET,
  1531. lpFontFunc, // callback
  1532. lParam, // user defined data
  1533. TYPE_ENUMFONTFAMILIESEX
  1534. );
  1535. }
  1536. /******************************Public*Routine******************************\
  1537. * GetFontResourceInfoW
  1538. *
  1539. * Client side stub.
  1540. *
  1541. * History:
  1542. * 2-Sep-1993 -by- Gerrit van Wingerden [gerritv]
  1543. * Made this a "W" function.
  1544. * 15-Jul-1991 -by- Gilman Wong [gilmanw]
  1545. * Wrote it.
  1546. \**************************************************************************/
  1547. BOOL GetFontResourceInfoW (
  1548. LPWSTR lpPathname,
  1549. LPDWORD lpBytes,
  1550. LPVOID lpBuffer,
  1551. DWORD iType)
  1552. {
  1553. ULONG cjBuffer = *lpBytes;
  1554. int cRet = 0;
  1555. FLONG flEmbed;
  1556. DWORD dwPidTid;
  1557. if ( (lpPathname != NULL) &&
  1558. ((cjBuffer == 0) || (lpBuffer != NULL)) )
  1559. {
  1560. if( iType == GFRI_TTFILENAME )
  1561. {
  1562. WCHAR awcPathname[MAX_PATH];
  1563. WCHAR awcTTF[MAX_PATH];
  1564. if (bMakePathNameW(awcPathname, lpPathname, NULL, NULL))
  1565. {
  1566. ULONG size;
  1567. if (size = cGetTTFFromFOT(awcPathname, MAX_PATH, awcTTF, NULL, &flEmbed, &dwPidTid, TRUE))
  1568. {
  1569. // For the case of GFRI_TTFILENAME, the file need not be already
  1570. // loaded. Which means a PFF may or may not exist for this file.
  1571. *lpBytes = size * sizeof(WCHAR);
  1572. if (cjBuffer)
  1573. {
  1574. // Also return the name if it fits
  1575. // if awcPathnmae points to a bad FOT file, awcTTF will contain the same FOT file name
  1576. // passed to the cGetTTTFromFOT. In this case, we want to return FALSE.
  1577. if ((cjBuffer >= *lpBytes) &&
  1578. ((size < 5) || _wcsicmp(&awcTTF[size-5], L".FOT")))
  1579. {
  1580. RtlMoveMemory(lpBuffer, awcTTF, *lpBytes);
  1581. }
  1582. else
  1583. {
  1584. // Buffer is too small - error !
  1585. // or bad FOT file, no TTF file
  1586. *lpBytes = 0;
  1587. }
  1588. }
  1589. cRet = (*lpBytes != 0);
  1590. }
  1591. }
  1592. }
  1593. else
  1594. {
  1595. // First get a real NT path Name before calling to the kernel
  1596. ULONG cwc,cFiles;
  1597. FLONG fl = 0; // essential initialization
  1598. WCHAR *pwszNtPath;
  1599. if (pwszNtPath = pwszAllocNtMultiplePath(lpPathname,
  1600. &fl,
  1601. &cwc,
  1602. &cFiles,
  1603. FALSE,
  1604. &dwPidTid,
  1605. TRUE))
  1606. {
  1607. cRet = NtGdiGetFontResourceInfoInternalW(
  1608. pwszNtPath,
  1609. cwc,
  1610. cFiles,
  1611. cjBuffer,
  1612. lpBytes,
  1613. lpBuffer,
  1614. iType);
  1615. LOCALFREE(pwszNtPath);
  1616. }
  1617. }
  1618. }
  1619. return( cRet );
  1620. }
  1621. /******************************Public*Routine******************************\
  1622. * bMakePathNameW (PWSZ pwszDst, PWSZ pwszSrc, PWSZ *ppwszFilePart)
  1623. *
  1624. * Converts the filename pszSrc into a fully qualified pathname pszDst.
  1625. * The parameter pszDst must point to a WCHAR buffer at least
  1626. * MAX_PATH*sizeof(WCHAR) bytes in size.
  1627. *
  1628. * An attempt is made find the file first in the new win95 directory
  1629. * %windows%\fonts (which also is the first directory in secure font path,
  1630. * if one is defined) and then we do the old fashioned windows stuff
  1631. * where SearchPathW searches directories in usual order
  1632. *
  1633. * ppwszFilePart is set to point to the last component of the pathname (i.e.,
  1634. * the filename part) in pwszDst. If this is null it is ignored.
  1635. *
  1636. * Returns:
  1637. * TRUE if sucessful, FALSE if an error occurs.
  1638. *
  1639. * History:
  1640. * Mon 02-Oct-1995 -by- Bodin Dresevic [BodinD]
  1641. * update: added font path stuff
  1642. * 30-Sep-1991 -by- Gilman Wong [gilmanw]
  1643. * Wrote it.
  1644. \**************************************************************************/
  1645. BOOL bMakePathNameW (
  1646. WCHAR *pwszDst,
  1647. WCHAR *pwszSrc,
  1648. WCHAR **ppwszFilePart,
  1649. FLONG *pfl
  1650. )
  1651. {
  1652. WCHAR * pwszD, * pwszS, * pwszF;
  1653. BOOL bOk;
  1654. ULONG ulPathLength = 0; // essential to initialize
  1655. ULONG cwcSystem;
  1656. ULONG cwcDst;
  1657. WCHAR *pwcTmp;
  1658. if (pfl)
  1659. *pfl = 0;
  1660. if (ppwszFilePart == NULL)
  1661. {
  1662. ppwszFilePart = &pwszF;
  1663. }
  1664. // init unicode path for the fonts directory, %windir%\fonts that is:
  1665. // This is always defined in NT versions > 3.51.
  1666. ENTERCRITICALSECTION(&semLocal);
  1667. bOk = bInitSystemAndFontsDirectoriesW(&gpwcSystemDir, &gpwcFontsDir);
  1668. LEAVECRITICALSECTION(&semLocal);
  1669. // bInitFontDirectoryW logs the error code and prints warning, just exit
  1670. if (!bOk)
  1671. return FALSE;
  1672. ASSERTGDI(gpwcFontsDir, "gpwcFontsDir not initialized\n");
  1673. // if relative path
  1674. if
  1675. (
  1676. (pwszSrc[0] != L'\\') &&
  1677. !((pwszSrc[1] == L':') && (pwszSrc[2] == L'\\'))
  1678. )
  1679. {
  1680. if (pfl)
  1681. {
  1682. *pfl |= FONT_RELATIVE_PATH;
  1683. }
  1684. // find out if the font file is in %windir%\fonts
  1685. ulPathLength = SearchPathW (
  1686. gpwcFontsDir,
  1687. pwszSrc,
  1688. NULL,
  1689. MAX_PATH,
  1690. pwszDst,
  1691. ppwszFilePart);
  1692. if (ulPathLength >= MAX_PATH)
  1693. {
  1694. WARNING("bMakePathNameW: path from SearchPathW is too long\n");
  1695. return FALSE;
  1696. }
  1697. #ifdef DEBUG_PATH
  1698. DbgPrint("SPW1: pwszSrc = %ws\n", pwszSrc);
  1699. if (ulPathLength)
  1700. DbgPrint("SPW1: pwszDst = %ws\n", pwszDst);
  1701. #endif // DEBUG_PATH
  1702. }
  1703. // Search for file using default windows path and return full pathname.
  1704. // We will only do so if we did not already find the font in the
  1705. // %windir%\fonts directory or if pswzSrc points to the full path
  1706. // in which case search path is ignored
  1707. if (ulPathLength == 0)
  1708. {
  1709. if (ulPathLength = SearchPathW (
  1710. NULL,
  1711. pwszSrc,
  1712. NULL,
  1713. MAX_PATH,
  1714. pwszDst,
  1715. ppwszFilePart))
  1716. {
  1717. if (ulPathLength >= MAX_PATH)
  1718. {
  1719. WARNING("bMakePathNameW: path from SearchPathW is too long\n");
  1720. return FALSE;
  1721. }
  1722. // let us figure it out if the font is in the
  1723. // system directory, or somewhere else along the path:
  1724. if (pfl)
  1725. {
  1726. cwcSystem = wcslen(gpwcSystemDir);
  1727. cwcDst = wcslen(pwszDst);
  1728. if (cwcDst > (cwcSystem + 1)) // + 1 for L'\\'
  1729. {
  1730. if (!_wcsnicmp(pwszDst, gpwcSystemDir, cwcSystem))
  1731. {
  1732. pwcTmp = &pwszDst[cwcSystem];
  1733. if (*pwcTmp == L'\\')
  1734. {
  1735. pwcTmp++; // skip it and see if there are any more of these in pszDst
  1736. for (;(pwcTmp < &pwszDst[cwcDst]) && (*pwcTmp != L'\\'); pwcTmp++)
  1737. ;
  1738. if (*pwcTmp != L'\\')
  1739. *pfl |= FONT_IN_SYSTEM_DIR;
  1740. }
  1741. }
  1742. }
  1743. }
  1744. }
  1745. #ifdef DEBUG_PATH
  1746. DbgPrint("SPW2: pwszSrc = %ws\n", pwszSrc);
  1747. if (ulPathLength)
  1748. DbgPrint("SPW2: pwszDst = %ws\n", pwszDst);
  1749. #endif // DEBUG_PATH
  1750. }
  1751. else
  1752. {
  1753. if (pfl)
  1754. {
  1755. *pfl |= FONT_IN_FONTS_DIR;
  1756. }
  1757. }
  1758. // finally we test to see if this is one of these fonts that were moved
  1759. // by setup during upgrade from system to fonts dir,
  1760. // but the registry entry for that font
  1761. // contained full path to system so that the code above would not have found
  1762. // this font. This code is only called by font sweeper as signified by
  1763. // pfl != NULL. More desription follows below
  1764. // This part of routine handles the upgrade situation where NT 3.51 font applet
  1765. // wrote the full path of the .fot file that lives in %windir%\system
  1766. // directory in the registry. This redundant situation happens
  1767. // when tt fonts are installed under 3.51 but ttf's are not copied
  1768. // to %windir%\system directory. Some ill behaved apps also write the
  1769. // full path of .fot files in the system directory in the registry.
  1770. // On upgrade for 4.0 the system setup copies all .fot files from
  1771. // system to fonts directory. bMakePathNameW will therefore fail to find
  1772. // the fot file because the file was moved to fonts by setup AND full,
  1773. // no longer correct path to fot file, is passed to this routine.
  1774. // That is why we try to find out if the full path is the one
  1775. // describing system dir and if so, retry to find .fot in fonts dir.
  1776. if (pfl && (ulPathLength == 0))
  1777. {
  1778. // first check if the full path to .fot file points to the
  1779. // file which USED to be in the system directory.
  1780. ULONG cwcFileName = wcslen(pwszSrc);
  1781. cwcSystem = wcslen(gpwcSystemDir);
  1782. if ((cwcFileName + 1) > cwcSystem) // + 1 for L'\\'
  1783. {
  1784. if (!_wcsnicmp(gpwcSystemDir, pwszSrc, cwcSystem))
  1785. {
  1786. pwszSrc += cwcSystem;
  1787. if (pwszSrc[0] == L'\\')
  1788. {
  1789. pwszSrc += 1; // skip L'\\'
  1790. // make sure there are no more directory separators L'\\' in
  1791. // the remaining path, ie. that this is indeed a relative path
  1792. for (pwcTmp = pwszSrc; *pwcTmp != L'\0'; pwcTmp++)
  1793. if (*pwcTmp == L'\\')
  1794. break;
  1795. // now check if the .fot file has been moved to fonts dir
  1796. if (*pwcTmp == L'\0')
  1797. {
  1798. ulPathLength = SearchPathW (
  1799. gpwcFontsDir,
  1800. pwszSrc,
  1801. NULL,
  1802. MAX_PATH,
  1803. pwszDst,
  1804. ppwszFilePart);
  1805. if (ulPathLength >= MAX_PATH)
  1806. {
  1807. WARNING("bMakePathNameW: path from SearchPathW is too long\n");
  1808. return FALSE;
  1809. }
  1810. if (ulPathLength)
  1811. *pfl |= FONT_IN_FONTS_DIR;
  1812. }
  1813. }
  1814. }
  1815. }
  1816. }
  1817. // If search was successful return TRUE:
  1818. return (ulPathLength != 0);
  1819. }
  1820. /******************************Private*Routine******************************\
  1821. *
  1822. * BOOL IsWinPERemoteBootDrive( PCWSTR Drive )
  1823. *
  1824. * History:
  1825. * July 19, 2001. acosma - Added routine.
  1826. *
  1827. \**************************************************************************/
  1828. static BOOL IsWinPERemoteBootDrive( PCWSTR Drive )
  1829. /*++
  1830. Routine Description:
  1831. Finds out if we are currently running on WinPE booted remotely.
  1832. Arguments:
  1833. None.
  1834. Return value:
  1835. TRUE if this is a WinPE remote boot otherwise FALSE.
  1836. --*/
  1837. {
  1838. static BOOL Result = FALSE;
  1839. static BOOL Initialized = FALSE;
  1840. static WCHAR WindowsDrive = 0;
  1841. if (!Initialized) {
  1842. WCHAR WindowsDir[MAX_PATH] = {0};
  1843. Initialized = TRUE;
  1844. if (GetWindowsDirectoryW(WindowsDir, sizeof(WindowsDir)/sizeof(WCHAR))) {
  1845. WindowsDir[3] = 0;
  1846. WindowsDrive = WindowsDir[0];
  1847. //
  1848. // If the drive type is DRIVE_REMOTE then we have booted from
  1849. // network.
  1850. //
  1851. Result = (GetDriveTypeW(WindowsDir) == DRIVE_REMOTE);
  1852. if (Result) {
  1853. OBJECT_ATTRIBUTES Obja;
  1854. UNICODE_STRING KeyName;
  1855. HKEY hKey = NULL;
  1856. NTSTATUS Status;
  1857. RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MiniNT");
  1858. InitializeObjectAttributes(&Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  1859. Status = NtOpenKey(&hKey, KEY_READ, &Obja);
  1860. if ( NT_SUCCESS (Status) ) {
  1861. Result = TRUE;
  1862. NtClose(hKey);
  1863. } else {
  1864. Result = FALSE;
  1865. }
  1866. }
  1867. }
  1868. }
  1869. //
  1870. // Is this WinPE remote boot and is the passed in drive valid & its windows drive?
  1871. //
  1872. return (Result && Drive && Drive[0] && (WindowsDrive == Drive[0]));
  1873. }
  1874. /******************************Public*Routine******************************\
  1875. *
  1876. * BOOL bFileIsOnTheHardDrive(PWCHAR pwszFullPathName)
  1877. *
  1878. * History:
  1879. * Fri 22-Jul-1994 -by- Gerrit van Wingerden [gerritv]
  1880. * Stole it from BodinD
  1881. \**************************************************************************/
  1882. BOOL bFileIsOnTheHardDrive(WCHAR *inputpwszFullPathName)
  1883. {
  1884. const WCHAR * pwszFullPathName = inputpwszFullPathName;
  1885. WCHAR awcDrive[4];
  1886. if (pwszFullPathName[1] != (WCHAR)':')
  1887. {
  1888. // the file path has the form \\foo\goo. Even though this could be
  1889. // a share on the local hard drive, this is not very likely. It is ok
  1890. // for the sake of simplicity to consider this a remote drive.
  1891. // The only side effect of this is that in this unlikely case the font
  1892. // would get unloaded at logoff and reloaded at logon time
  1893. return FALSE;
  1894. }
  1895. // make a zero terminated string with drive string
  1896. // to be feed into GetDriveType api. The string has to have the form: "x:\"
  1897. awcDrive[0] = pwszFullPathName[0]; // COPY DRIVE LETTER
  1898. awcDrive[1] = pwszFullPathName[1]; // COPY ':'
  1899. awcDrive[2] = (CHAR)'\\'; // obvious
  1900. awcDrive[3] = (CHAR)'\0'; // zero terminate
  1901. if ( IsWinPERemoteBootDrive(awcDrive) )
  1902. {
  1903. // If we are in WinPE and this is a remote boot then always return true
  1904. // to this so that we don't wait until logon to load fonts, since in
  1905. // WinPE we don't logon, and the system drive is a net drive but we
  1906. // already have credentials to access it since the OS is booting from
  1907. // there
  1908. // Doing this after checking for the \\foo\goo so that we don't accidentaly
  1909. // try to load fonts that ARE really on some net share in the
  1910. // Remote boot WinPE case.
  1911. //
  1912. return TRUE;
  1913. }
  1914. // for this pupose, only net drives are not considered hard drives
  1915. // so that we can boot of Bernoulli removable drives
  1916. switch (GetDriveTypeW((LPCWSTR)awcDrive))
  1917. {
  1918. case DRIVE_REMOVABLE:
  1919. case DRIVE_FIXED:
  1920. case DRIVE_CDROM:
  1921. case DRIVE_RAMDISK:
  1922. return 1;
  1923. default:
  1924. return 0;
  1925. }
  1926. }
  1927. static
  1928. WCHAR * pwszAllocNtMultiplePath(
  1929. LPWSTR pwszFileName,
  1930. FLONG *pfl,
  1931. ULONG *pcwc,
  1932. ULONG *pcFiles,
  1933. BOOL bAddFR, // called by add or remove fr
  1934. DWORD *pdwPidTid, // PID/TID for embedded font
  1935. BOOL bChkFOT
  1936. )
  1937. {
  1938. BOOL bDoIt = FALSE;
  1939. BOOL bReturn = TRUE;
  1940. ULONG cwc;
  1941. ULONG iFile;
  1942. ULONG cFiles = 1; // number of paths separated by | separator
  1943. WCHAR *pwszOneFile;
  1944. WCHAR *pwchMem;
  1945. WCHAR *pwcNtPaths;
  1946. FLONG flTmp = 0; // essential initialization
  1947. FLONG fl = (pfl ? *pfl : 0); // essential initialization
  1948. FLONG flEmbed = 0;
  1949. UINT cbCombinedPaths = 0;
  1950. // scan the string to figure out how many individual file names are
  1951. // in the input string:
  1952. for (pwszOneFile = pwszFileName; *pwszOneFile; pwszOneFile++)
  1953. {
  1954. if (*pwszOneFile == PATH_SEPARATOR)
  1955. cFiles++;
  1956. }
  1957. // allocate memory where NtPathNames are going to be stored:
  1958. // we allow only file names with MAX_PATH-1 characters or less
  1959. // after all the path transformations
  1960. cbCombinedPaths = cFiles * sizeof(WCHAR) * MAX_PATH;
  1961. pwchMem = (WCHAR *)LOCALALLOC(cbCombinedPaths);
  1962. if (pwchMem)
  1963. {
  1964. // set the pointers for the loop:
  1965. pwcNtPaths = pwchMem;
  1966. pwszOneFile = pwszFileName; // reset this from the loop above
  1967. cwc = 0; // measure the whole NtPaths string
  1968. bDoIt = TRUE;
  1969. for (iFile = 0; iFile < cFiles; iFile++)
  1970. {
  1971. WCHAR awchOneFile[MAX_PATH];
  1972. WCHAR awcPathName[MAX_PATH];
  1973. WCHAR awcTTF[MAX_PATH];
  1974. WCHAR *pwcTmp = awchOneFile;
  1975. // copy the file to the buffer on the stack and zero terminate it
  1976. // the whole point of this is just to ensure zero termination
  1977. while ((*pwszOneFile != L'\0') && (*pwszOneFile != PATH_SEPARATOR))
  1978. {
  1979. *pwcTmp = *pwszOneFile;
  1980. ++pwcTmp, ++pwszOneFile;
  1981. if (pwcTmp - awchOneFile >= MAX_PATH)
  1982. {
  1983. WARNING("pwszAllocNtMultiplePath: source path is too long\n");
  1984. bDoIt = FALSE;
  1985. goto failure;
  1986. }
  1987. }
  1988. pwszOneFile++; // skip the separator or terminating zero
  1989. *pwcTmp = L'\0'; // zero terminate
  1990. if
  1991. (
  1992. bMakePathNameW(awcPathName, awchOneFile,NULL,NULL) &&
  1993. cGetTTFFromFOT(awcPathName, MAX_PATH, awcTTF, NULL, &flEmbed, pdwPidTid, bChkFOT)
  1994. )
  1995. {
  1996. // we have to make sure that the font lies in the font path
  1997. // if one is defined. This needs to be done before converting
  1998. // to NtPathNames because the names in the registry are "dos"
  1999. // path names, not Nt path names
  2000. UNICODE_STRING UniStr;
  2001. ULONG cwcThis;
  2002. // the next portion of code is only done for AddFontResourceCase
  2003. if (bAddFR)
  2004. {
  2005. if (bFileIsOnTheHardDrive(awcTTF))
  2006. flTmp |= AFRW_ADD_LOCAL_FONT;
  2007. else
  2008. flTmp |= AFRW_ADD_REMOTE_FONT;
  2009. }
  2010. // let us check the error return here:
  2011. bReturn = RtlDosPathNameToNtPathName_U(awcTTF,
  2012. &UniStr,
  2013. NULL,
  2014. NULL);
  2015. // get the size out of the unicode string,
  2016. // update cwc, copy out, and then free the memory
  2017. if (bReturn && (UniStr.Buffer))
  2018. {
  2019. cwcThis = (UniStr.Length/sizeof(WCHAR) + 1);
  2020. if (cwcThis <= MAX_PATH)
  2021. {
  2022. cwc += cwcThis;
  2023. RtlCopyMemory(pwcNtPaths, UniStr.Buffer, UniStr.Length);
  2024. if (iFile < (cFiles - 1))
  2025. pwcNtPaths[cwcThis - 1] = PATH_SEPARATOR;
  2026. else
  2027. pwcNtPaths[cwcThis - 1] = L'\0';
  2028. pwcNtPaths += cwcThis;
  2029. }
  2030. else
  2031. {
  2032. WARNING("pwszAllocNtMultiplePath: path from RtlDosPathNameToNtPathName_U is too long\n");
  2033. bDoIt = FALSE;
  2034. }
  2035. RtlFreeHeap(RtlProcessHeap(),0,UniStr.Buffer);
  2036. }
  2037. else
  2038. {
  2039. bDoIt = FALSE;
  2040. }
  2041. }
  2042. else
  2043. {
  2044. bDoIt = FALSE;
  2045. }
  2046. if (!bDoIt)
  2047. break;
  2048. } // end of the "for" loop
  2049. failure:
  2050. // now check if we are going to reject the font because
  2051. // only local or only remote fonts are requested to be loaded
  2052. if (bDoIt && bAddFR)
  2053. {
  2054. switch (fl & (AFRW_ADD_REMOTE_FONT|AFRW_ADD_LOCAL_FONT))
  2055. {
  2056. case AFRW_ADD_REMOTE_FONT:
  2057. // we say that the font is remote if AT LEAST ONE of the files
  2058. // is remote.
  2059. if (!(flTmp & AFRW_ADD_REMOTE_FONT))
  2060. bDoIt = FALSE;
  2061. break;
  2062. case AFRW_ADD_LOCAL_FONT:
  2063. // conversely, we say that it is local when it is not remote,
  2064. // that is when ALL files are local
  2065. if (flTmp & AFRW_ADD_REMOTE_FONT)
  2066. bDoIt = FALSE;
  2067. break;
  2068. case (AFRW_ADD_REMOTE_FONT|AFRW_ADD_LOCAL_FONT):
  2069. RIP("AddFontResourceW, bogus flag combination");
  2070. bDoIt = FALSE;
  2071. break;
  2072. default:
  2073. // flag if this font should be removed at the log off time
  2074. if (flTmp & AFRW_ADD_REMOTE_FONT)
  2075. {
  2076. // always remove fonts on the net on the log off,
  2077. // whether they be listed in the registry or not.
  2078. // The point is that even if they are listed, drive letters
  2079. // may change if a different user logs on. If this font is
  2080. // NOT in the registry, it is a temporary remote font added
  2081. // by an app, so we want it removed on the next log off.
  2082. *pfl |= AFRW_ADD_REMOTE_FONT;
  2083. }
  2084. else
  2085. {
  2086. // do not remove, even if not in the registry, i.e. even
  2087. // if this is a temp. font added by some app. This is ok
  2088. // since this is a local font, drive letter destinations
  2089. // do not change even when a different user logs on. Note
  2090. // that this is little bit different that 3.51 behavior.
  2091. // This way every font is marked at AddFontResource time
  2092. // for whether it should be removed or not at log off time.
  2093. // This makes time consuming registry searches at log off
  2094. // time unnecessary. The drawback is that the next user
  2095. // to log on may still have local temp fonts loaded
  2096. // from a previous user's session
  2097. *pfl |= AFRW_ADD_LOCAL_FONT;
  2098. }
  2099. break;
  2100. }
  2101. }
  2102. }
  2103. if (!bDoIt)
  2104. {
  2105. *pcwc = 0;
  2106. *pcFiles = 0;
  2107. if (pwchMem)
  2108. {
  2109. LOCALFREE(pwchMem);
  2110. pwchMem = NULL;
  2111. }
  2112. }
  2113. else // success
  2114. {
  2115. *pcwc = cwc;
  2116. *pcFiles = cFiles;
  2117. // set flag for embedded fonts
  2118. *pfl |= flEmbed;
  2119. ASSERTGDI((flEmbed & (FRW_EMB_PID|FRW_EMB_TID)) == flEmbed, "Embedded fonts: flEmbed\n");
  2120. ASSERTGDI((!flEmbed) || (cFiles == 1), "Embedded fonts but cFiles != 1\n");
  2121. }
  2122. return pwchMem;
  2123. }
  2124. int GdiAddFontResourceW (
  2125. LPWSTR pwszFileName, // ptr. to unicode filename string
  2126. FLONG fl,
  2127. DESIGNVECTOR *pdv
  2128. )
  2129. {
  2130. int iRet = 0;
  2131. ULONG cFiles, cwc;
  2132. WCHAR *pwszNtPath;
  2133. DWORD dwPidTid;
  2134. if (pwszNtPath = pwszAllocNtMultiplePath(pwszFileName,
  2135. &fl,
  2136. &cwc,
  2137. &cFiles,
  2138. TRUE,
  2139. &dwPidTid, FALSE))
  2140. {
  2141. iRet = NtGdiAddFontResourceW(pwszNtPath,cwc,
  2142. cFiles,fl,dwPidTid, pdv);
  2143. LOCALFREE(pwszNtPath);
  2144. if (!iRet)
  2145. {
  2146. pwszNtPath = NULL;
  2147. cFiles = 0;
  2148. cwc = 0;
  2149. dwPidTid = 0;
  2150. if (pwszNtPath = pwszAllocNtMultiplePath(pwszFileName,
  2151. &fl,
  2152. &cwc,
  2153. &cFiles,
  2154. TRUE,
  2155. &dwPidTid, TRUE))
  2156. {
  2157. iRet = NtGdiAddFontResourceW(pwszNtPath,cwc,
  2158. cFiles,fl,dwPidTid, pdv);
  2159. LOCALFREE(pwszNtPath);
  2160. }
  2161. }
  2162. }
  2163. return iRet;
  2164. }
  2165. /******************************Public*Routine******************************\
  2166. *
  2167. * int WINAPI AddFontResource(LPSTR psz)
  2168. *
  2169. * History:
  2170. * 13-Aug-1991 -by- Bodin Dresevic [BodinD]
  2171. * Wrote it.
  2172. \**************************************************************************/
  2173. int WINAPI AddFontResourceA(LPCSTR psz)
  2174. {
  2175. return AddFontResourceExA(psz,0, NULL);
  2176. }
  2177. /******************************Public*Routine******************************\
  2178. *
  2179. * int WINAPI AddFontResourceExA(LPSTR psz, DWORD dwFlag, PVOID NULL)
  2180. *
  2181. * History:
  2182. * 29-Aug-1996 -by- Xudong Wu [TessieW]
  2183. * Wrote it.
  2184. \**************************************************************************/
  2185. int WINAPI AddFontResourceExA(LPCSTR psz, DWORD fl, PVOID pvResrved)
  2186. {
  2187. int iRet = 0;
  2188. WCHAR awcPathName[MAX_PATH];
  2189. ULONG cch, cwc;
  2190. WCHAR *pwcPathName = NULL;
  2191. DESIGNVECTOR * pdv = NULL;
  2192. // check invalid flag
  2193. if ( fl & ~(FR_PRIVATE | FR_NOT_ENUM) )
  2194. {
  2195. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2196. return 0;
  2197. }
  2198. // protect ourselves from bogus pointers, win95 does it
  2199. try
  2200. {
  2201. cch = lstrlenA(psz) + 1;
  2202. if (cch <= MAX_PATH)
  2203. {
  2204. pwcPathName = awcPathName;
  2205. cwc = MAX_PATH;
  2206. }
  2207. else
  2208. {
  2209. pwcPathName = (WCHAR *)LOCALALLOC(cch * sizeof(WCHAR));
  2210. cwc = cch;
  2211. }
  2212. if (pwcPathName)
  2213. {
  2214. vToUnicodeN(pwcPathName, cwc, psz, cch);
  2215. iRet = 1;
  2216. }
  2217. }
  2218. except(EXCEPTION_EXECUTE_HANDLER)
  2219. {
  2220. iRet = 0;
  2221. }
  2222. if (iRet)
  2223. iRet = GdiAddFontResourceW(pwcPathName,(FLONG)fl, pdv);
  2224. if (pwcPathName && (pwcPathName != awcPathName))
  2225. LOCALFREE(pwcPathName);
  2226. return iRet;
  2227. }
  2228. /**************************Public*Routine************************\
  2229. * int WINAPI AddFontMemResourceEx()
  2230. *
  2231. * Font image pointed by pFileView is loaded as private font
  2232. * (FR_PRIVATE | FR_NOT_ENUM) to the system private font tale.
  2233. *
  2234. * If succeeds, it returns an index to the global memory font
  2235. * link list, otherwise it returns zero.
  2236. *
  2237. * History:
  2238. * 20-May-1997 -by- Xudong Wu [TessieW]
  2239. * Wrote it.
  2240. \****************************************************************/
  2241. HANDLE WINAPI AddFontMemResourceEx
  2242. (
  2243. PVOID pFileView,
  2244. DWORD cjSize,
  2245. PVOID pvResrved,
  2246. DWORD* pNumFonts)
  2247. {
  2248. DWORD cjDV = 0;
  2249. DESIGNVECTOR * pdv = NULL;
  2250. // check size and pointer
  2251. if ((cjSize == 0) || (pFileView == NULL) || (pNumFonts == NULL))
  2252. {
  2253. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2254. return 0;
  2255. }
  2256. if (pdv)
  2257. {
  2258. cjDV = SIZEOFDV(pdv->dvNumAxes);
  2259. }
  2260. return (NtGdiAddFontMemResourceEx(pFileView, cjSize, pdv, cjDV, pNumFonts));
  2261. }
  2262. /******************************Public*Routine******************************\
  2263. *
  2264. * int WINAPI AddFontResourceTracking(LPSTR psz)
  2265. *
  2266. * This routine calls AddFontResource and, if succesful, keeps track of the
  2267. * call along with an unique id identifying the apps. Later when the app
  2268. * goes away, WOW will call RemoveNetFonts to remove all of these added fonts
  2269. * if there are on a net share.
  2270. *
  2271. * History:
  2272. * Fri 22-Jul-1994 -by- Gerrit van Wingerden [gerritv]
  2273. * Wrote it.
  2274. \**************************************************************************/
  2275. int AddFontResourceTracking(LPCSTR psz, UINT id)
  2276. {
  2277. INT iRet;
  2278. AFRTRACKNODE *afrtnNext;
  2279. WCHAR awcPathBuffer[MAX_PATH],*pTmp;
  2280. WCHAR awcPathName[MAX_PATH];
  2281. BOOL bResult;
  2282. vToUnicodeN(awcPathName, MAX_PATH, psz, lstrlenA(psz) + 1);
  2283. iRet = GdiAddFontResourceW(awcPathName, 0 , NULL);
  2284. if( iRet == 0 )
  2285. {
  2286. // we failed so just return
  2287. return(iRet);
  2288. }
  2289. // now get the full pathname of the font
  2290. if (!bMakePathNameW(awcPathBuffer,awcPathName, &pTmp, NULL))
  2291. {
  2292. WARNING("AddFontResourceTracking unable to create path\n");
  2293. return(iRet);
  2294. }
  2295. // if this isn't a network font just return
  2296. if( bFileIsOnTheHardDrive( awcPathBuffer ) )
  2297. {
  2298. return(iRet);
  2299. }
  2300. // now search the list
  2301. for( afrtnNext = pAFRTNodeList;
  2302. afrtnNext != NULL;
  2303. afrtnNext = afrtnNext->pafrnNext
  2304. )
  2305. {
  2306. if( ( !_wcsicmp( awcPathBuffer, afrtnNext->pwszPath ) ) &&
  2307. ( id == afrtnNext->id ))
  2308. {
  2309. // we've found an entry so update the count and get out of here
  2310. afrtnNext->cLoadCount += 1;
  2311. return(iRet);
  2312. }
  2313. }
  2314. // if we got here this font isn't yet in the list so we need to add it
  2315. afrtnNext = (AFRTRACKNODE *) LOCALALLOC( sizeof(AFRTRACKNODE) +
  2316. ( sizeof(WCHAR) * ( wcslen( awcPathBuffer ) + 1)) );
  2317. if( afrtnNext == NULL )
  2318. {
  2319. WARNING("AddFontResourceTracking unable to allocate memory\n");
  2320. return(iRet);
  2321. }
  2322. // link it in
  2323. afrtnNext->pafrnNext = pAFRTNodeList;
  2324. pAFRTNodeList = afrtnNext;
  2325. // the path string starts just past afrtnNext in our recently allocated buffer
  2326. afrtnNext->pwszPath = (WCHAR*) (&afrtnNext[1]);
  2327. lstrcpyW( afrtnNext->pwszPath, awcPathBuffer );
  2328. afrtnNext->id = id;
  2329. afrtnNext->cLoadCount = 1;
  2330. return(iRet);
  2331. }
  2332. /******************************Public*Routine******************************\
  2333. *
  2334. * int RemoveFontResourceEntry( UINT id, CHAR *pszFaceName )
  2335. *
  2336. * Either search for an entry for a particlur task id and font file or and
  2337. * decrement the load count for it or, if pszPathName is NULL unload all
  2338. * fonts loaded by the task.
  2339. *
  2340. * History:
  2341. * Fri 22-Jul-1994 -by- Gerrit van Wingerden [gerritv]
  2342. * Wrote it.
  2343. \**************************************************************************/
  2344. void RemoveFontResourceEntry( UINT id, WCHAR *pwszPathName )
  2345. {
  2346. AFRTRACKNODE *afrtnNext,**ppafrtnPrev;
  2347. BOOL bMore = TRUE;
  2348. while( bMore )
  2349. {
  2350. for( afrtnNext = pAFRTNodeList, ppafrtnPrev = &pAFRTNodeList;
  2351. afrtnNext != NULL;
  2352. afrtnNext = afrtnNext->pafrnNext )
  2353. {
  2354. if( (( pwszPathName == NULL ) ||
  2355. ( !_wcsicmp( pwszPathName, afrtnNext->pwszPath ))) &&
  2356. ( id == afrtnNext->id ))
  2357. {
  2358. // we've found an entry so break
  2359. break;
  2360. }
  2361. ppafrtnPrev = &(afrtnNext->pafrnNext);
  2362. }
  2363. if( afrtnNext == NULL )
  2364. {
  2365. bMore = FALSE;
  2366. }
  2367. else
  2368. {
  2369. if( pwszPathName == NULL )
  2370. {
  2371. // we need to call RemoveFontResource LoadCount times to remove this font
  2372. while( afrtnNext->cLoadCount )
  2373. {
  2374. RemoveFontResourceW( afrtnNext->pwszPath );
  2375. afrtnNext->cLoadCount -= 1;
  2376. }
  2377. }
  2378. else
  2379. {
  2380. afrtnNext->cLoadCount -= 1;
  2381. // we're only decrementing the ref count so we are done
  2382. bMore = FALSE;
  2383. }
  2384. // now unlink it and a free the memory if the ref count is zero
  2385. if( afrtnNext->cLoadCount == 0 )
  2386. {
  2387. *ppafrtnPrev = afrtnNext->pafrnNext;
  2388. LOCALFREE(afrtnNext);
  2389. }
  2390. }
  2391. }
  2392. }
  2393. /******************************Public*Routine******************************\
  2394. *
  2395. * int RemoveFontResourceTracking(LPSTR psz)
  2396. *
  2397. * History:
  2398. * Fri 22-Jul-1994 -by- Gerrit van Wingerden [gerritv]
  2399. * Wrote it.
  2400. \**************************************************************************/
  2401. int RemoveFontResourceTracking(LPCSTR psz, UINT id)
  2402. {
  2403. INT iRet;
  2404. WCHAR awcPathBuffer[MAX_PATH],*pTmp;
  2405. WCHAR awcPathName[MAX_PATH];
  2406. BOOL bResult;
  2407. vToUnicodeN(awcPathName, MAX_PATH, psz, lstrlenA(psz) + 1);
  2408. #if DBG
  2409. DbgPrint("We made it to RemoveFontsResourceTracking %s\n", psz);
  2410. #endif
  2411. iRet = RemoveFontResourceW( awcPathName );
  2412. if( iRet == 0 )
  2413. {
  2414. // we failed so just return
  2415. return(iRet);
  2416. }
  2417. // now get the full pathname of the font
  2418. if (!bMakePathNameW(awcPathBuffer, awcPathName, &pTmp, NULL))
  2419. {
  2420. WARNING("RemoveFontResourceTracking unable to create path\n");
  2421. return(iRet);
  2422. }
  2423. #if DBG
  2424. DbgPrint("Path is %ws\n", awcPathBuffer);
  2425. #endif
  2426. // if this isn't a network font just return
  2427. if( bFileIsOnTheHardDrive( awcPathBuffer ) )
  2428. {
  2429. return(iRet);
  2430. }
  2431. // now search the list decrement the reference count
  2432. RemoveFontResourceEntry( id, awcPathBuffer );
  2433. return(iRet);
  2434. }
  2435. void UnloadNetworkFonts( UINT id )
  2436. {
  2437. RemoveFontResourceEntry( id, NULL );
  2438. }
  2439. /******************************Public*Routine******************************\
  2440. *
  2441. * int WINAPI AddFontResourceW(LPWSTR pwsz)
  2442. *
  2443. * History:
  2444. * 13-Aug-1991 -by- Bodin Dresevic [BodinD]
  2445. * Wrote it.
  2446. \**************************************************************************/
  2447. int WINAPI AddFontResourceW(LPCWSTR pwsz)
  2448. {
  2449. return GdiAddFontResourceW((LPWSTR) pwsz, 0 , NULL);
  2450. }
  2451. /******************************Public*Routine******************************\
  2452. *
  2453. * int WINAPI AddFontResourceExW
  2454. *
  2455. * History:
  2456. * 29-Aug-1996 -by- Xudong Wu [TessieW]
  2457. * Wrote it.
  2458. \**************************************************************************/
  2459. int WINAPI AddFontResourceExW(LPCWSTR pwsz, DWORD fl, PVOID pvResrved)
  2460. {
  2461. DESIGNVECTOR * pdv = NULL;
  2462. // check invalid flag
  2463. if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
  2464. {
  2465. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2466. return 0;
  2467. }
  2468. return GdiAddFontResourceW((LPWSTR) pwsz, (FLONG)fl , pdv);
  2469. }
  2470. /******************************Public*Routine******************************\
  2471. *
  2472. * BOOL WINAPI RemoveFontResource(LPSTR psz)
  2473. *
  2474. *
  2475. * History:
  2476. * 13-Aug-1991 -by- Bodin Dresevic [BodinD]
  2477. * Wrote it.
  2478. \**************************************************************************/
  2479. BOOL WINAPI RemoveFontResourceA(LPCSTR psz)
  2480. {
  2481. return RemoveFontResourceExA(psz,0, NULL);
  2482. }
  2483. /******************************Public*Routine******************************\
  2484. *
  2485. * BOOL WINAPI RemoveFontResourceExA
  2486. *
  2487. * Note: Process should use the same flag with the one for AddFontResourceExA
  2488. * to remove the font resource
  2489. *
  2490. * History:
  2491. * 27-Sept-1996 -by- Xudong Wu [TessieW]
  2492. * Wrote it.
  2493. \**************************************************************************/
  2494. BOOL WINAPI RemoveFontResourceExA(LPCSTR psz, DWORD fl, PVOID pvResrved)
  2495. {
  2496. BOOL bRet = FALSE;
  2497. WCHAR awcPathName[MAX_PATH];
  2498. ULONG cch, cwc;
  2499. WCHAR *pwcPathName = NULL;
  2500. DESIGNVECTOR * pdv = NULL;
  2501. // check invalid flag
  2502. if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
  2503. {
  2504. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2505. return 0;
  2506. }
  2507. // protect ourselves from bogus pointers, win95 does it
  2508. try
  2509. {
  2510. cch = lstrlenA(psz) + 1;
  2511. if (cch <= MAX_PATH)
  2512. {
  2513. pwcPathName = awcPathName;
  2514. cwc = MAX_PATH;
  2515. }
  2516. else
  2517. {
  2518. pwcPathName = (WCHAR *)LOCALALLOC(cch * sizeof(WCHAR));
  2519. cwc = cch;
  2520. }
  2521. if (pwcPathName)
  2522. {
  2523. vToUnicodeN(pwcPathName, cwc, psz, lstrlenA(psz) + 1);
  2524. bRet = 1;
  2525. }
  2526. }
  2527. except(EXCEPTION_EXECUTE_HANDLER)
  2528. {
  2529. bRet = 0;
  2530. }
  2531. if (bRet)
  2532. bRet = RemoveFontResourceExW(pwcPathName,fl, NULL);
  2533. if (pwcPathName && (pwcPathName != awcPathName))
  2534. LOCALFREE(pwcPathName);
  2535. return bRet;
  2536. }
  2537. /******************************Public*Routine******************************\
  2538. *
  2539. * BOOL WINAPI RemoveFontResourceW(LPWSTR pwsz)
  2540. *
  2541. * History:
  2542. * 13-Aug-1991 -by- Bodin Dresevic [BodinD]
  2543. * Wrote it.
  2544. \**************************************************************************/
  2545. BOOL WINAPI RemoveFontResourceW(LPCWSTR pwsz)
  2546. {
  2547. return RemoveFontResourceExW(pwsz,0, NULL);
  2548. }
  2549. /******************************Public*Routine******************************\
  2550. *
  2551. * BOOL WINAPI RemoveFontResourceExW
  2552. *
  2553. * Note: needs to pass fl and dwPidTid for Embedded fonts
  2554. * History:
  2555. * 27-Sept-1996 -by- Xudong Wu [TessieW]
  2556. * Wrote it.
  2557. \**************************************************************************/
  2558. BOOL WINAPI RemoveFontResourceExW(LPCWSTR pwsz, DWORD dwfl, PVOID pvResrved)
  2559. {
  2560. BOOL bRet = FALSE;
  2561. ULONG cFiles, cwc;
  2562. FLONG fl = dwfl;
  2563. WCHAR *pwszNtPath;
  2564. DWORD dwPidTid;
  2565. DESIGNVECTOR * pdv = NULL;
  2566. // check invalid flag
  2567. if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
  2568. {
  2569. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2570. return 0;
  2571. }
  2572. if (pwsz)
  2573. {
  2574. if (pwszNtPath = pwszAllocNtMultiplePath((LPWSTR)pwsz,
  2575. &fl,
  2576. &cwc,
  2577. &cFiles,
  2578. FALSE,
  2579. &dwPidTid, TRUE))
  2580. {
  2581. bRet = NtGdiRemoveFontResourceW(pwszNtPath, cwc,
  2582. cFiles, fl, dwPidTid,
  2583. pdv);
  2584. LOCALFREE(pwszNtPath);
  2585. }
  2586. }
  2587. return bRet;
  2588. }
  2589. /**************************Public*Routine************************\
  2590. *
  2591. * BOOL WINAPI RemoveFontMemResourceEx()
  2592. *
  2593. * Note: current process can only remove the memory fonts loaded
  2594. * by itself.
  2595. *
  2596. * History:
  2597. * 20-May-1997 -by- Xudong Wu [TessieW]
  2598. * Wrote it.
  2599. \****************************************************************/
  2600. BOOL WINAPI RemoveFontMemResourceEx(HANDLE hMMFont)
  2601. {
  2602. if (hMMFont == 0)
  2603. {
  2604. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2605. return FALSE;
  2606. }
  2607. return (NtGdiRemoveFontMemResourceEx(hMMFont));
  2608. }
  2609. /******************************Public*Routine******************************\
  2610. * CreateScalableFontResourceA
  2611. *
  2612. * Client side stub (ANSI version) to GreCreateScalableFontResourceW.
  2613. *
  2614. * History:
  2615. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  2616. * Wrote it.
  2617. \**************************************************************************/
  2618. BOOL APIENTRY CreateScalableFontResourceA(
  2619. DWORD flHidden, // mark file as embedded font
  2620. LPCSTR lpszResourceFile, // name of file to create
  2621. LPCSTR lpszFontFile, // name of font file to use
  2622. LPCSTR lpszCurrentPath) // path to font file
  2623. {
  2624. // Allocate stack space for UNICODE version of input strings.
  2625. WCHAR awchResourceFile[MAX_PATH];
  2626. WCHAR awchFontFile[MAX_PATH];
  2627. WCHAR awchCurrentPath[MAX_PATH];
  2628. // Parameter checking.
  2629. if ( (lpszFontFile == (LPSTR) NULL) ||
  2630. (lpszResourceFile == (LPSTR) NULL)
  2631. )
  2632. {
  2633. WARNING("gdi!CreateScalableFontResourceA(): bad parameter\n");
  2634. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2635. return (FALSE);
  2636. }
  2637. // Convert input strings to UNICODE.
  2638. vToUnicodeN(awchResourceFile, MAX_PATH, lpszResourceFile, lstrlenA(lpszResourceFile)+1);
  2639. vToUnicodeN(awchFontFile, MAX_PATH, lpszFontFile, lstrlenA(lpszFontFile)+1);
  2640. // Note: Whereas the other parameters may be not NULL, lpszCurrentPath
  2641. // may be NULL. Therefore, we need to treat it a little
  2642. // differently.
  2643. if ( lpszCurrentPath != (LPSTR) NULL )
  2644. {
  2645. vToUnicodeN(awchCurrentPath, MAX_PATH, lpszCurrentPath, lstrlenA(lpszCurrentPath)+1);
  2646. }
  2647. else
  2648. {
  2649. awchCurrentPath[0] = L'\0'; // equivalent to NULL pointer for this call
  2650. }
  2651. // Call to UNICODE version of call.
  2652. return (CreateScalableFontResourceW (
  2653. flHidden,
  2654. awchResourceFile,
  2655. awchFontFile,
  2656. awchCurrentPath
  2657. )
  2658. );
  2659. }
  2660. /******************************Public*Routine******************************\
  2661. * CreateScalableFontResourceInternalW
  2662. *
  2663. * Creates a font resource file that contains the font directory and the name
  2664. * of the name of the scalable font file.
  2665. *
  2666. * The flEmbed flag marks the created file as hidden (or embedded). When an
  2667. * embedded font file is added to the system, it is hidden from enumeration
  2668. * and may be mapped to only if the bit is set in the LOGFONT.
  2669. *
  2670. * With regard to pwszCurrentPath and pwszFontFile, two cases are valid:
  2671. *
  2672. * 1. pwszCurrentPath is a path (relative, full, etc.)
  2673. * pwszFontFile is only FILENAME.EXT
  2674. *
  2675. * In this case, pwszFontFile is stored in the resource file. The caller
  2676. * is responsible for copying the .TTF file to the \windows\system
  2677. * directory.
  2678. *
  2679. * 2. pwszCurrentPath is NULL or a pointer to NULL
  2680. * pwszFontFile is a FULL pathname
  2681. *
  2682. * In this case, pwszFontFile is stored in the resource file. The
  2683. * file must always exist at this pathname.
  2684. *
  2685. * Returns:
  2686. * TRUE if successful, FALSE otherwise.
  2687. *
  2688. * History:
  2689. * 12-Apr-1995 Gerrit van Wingerden [gerritv]
  2690. * Moved it to client side for kernel mode.
  2691. * 10-Feb-1992 -by- Gilman Wong [gilmanw]
  2692. * Wrote it.
  2693. \**************************************************************************/
  2694. #define vToASCIIN( pszDst, cch, pwszSrc, cwch) \
  2695. { \
  2696. RtlUnicodeToMultiByteN((PCH)(pszDst), (ULONG)(cch), (PULONG)NULL, \
  2697. (PWSZ)(pwszSrc), (ULONG)((cwch)*sizeof(WCHAR))); \
  2698. (pszDst)[(cch)-1] = 0; \
  2699. }
  2700. BOOL CreateScalableFontResourceInternalW (
  2701. FLONG flEmbed, // fl
  2702. LPCWSTR lpwszResourceFile,
  2703. LPCWSTR lpwszFontFile,
  2704. LPCWSTR lpwszCurrentPath
  2705. )
  2706. {
  2707. BOOL bFullPath = TRUE; //!localW nIsNotFullPath
  2708. ULONG cwchFileName = 0; // localW nFileNameLength
  2709. ULONG cwchFullPath = 0; // localW nFullPathLength
  2710. ULONG cwchModuleName = 0; // localW nModuleNameLength
  2711. PWSZ pwszModuleName; // localD lpModuleName
  2712. PTRDIFF dpwszFullPath; // lovalW wFullPath
  2713. ULONG cjFontDir; // localW nSizeFontDir
  2714. ULONG cchFaceName; // localW nFaceNameLength
  2715. PSZ pszFaceName; // localD lpFaceName
  2716. PBYTE pjOutObj; // localD <lpFontDir, lpOutObj>
  2717. HANDLE hResFile; // localW hResFile
  2718. WCHAR awchFullPath[MAX_PATH]; // localV pFullPath, PATH_LENGTH
  2719. PWSZ pwszFullPath;
  2720. PWSZ pwszTmp;
  2721. ULONG cwch;
  2722. BYTE ajFontDir[CJ_FONTDIR];
  2723. PSZ pszTmp;
  2724. BYTE ajOutObj[CJ_OUTOBJ];
  2725. USHORT usTmp;
  2726. // Parameter check.
  2727. if ( (lpwszFontFile == (LPWSTR) NULL) ||
  2728. (lpwszResourceFile == (LPWSTR) NULL)
  2729. )
  2730. {
  2731. WARNING("CreateScalableFontResourceInternalW(): bad parameter\n");
  2732. return (FALSE);
  2733. }
  2734. // If not a NULL ptr, put current path in the full path.
  2735. pwszFullPath = awchFullPath;
  2736. if ( lpwszCurrentPath != (LPWSTR) NULL )
  2737. {
  2738. // Copy current path including the NULL.
  2739. pwszTmp = (PWSZ) lpwszCurrentPath;
  2740. while ( *pwszFullPath++ = *pwszTmp++ );
  2741. cwchFullPath = (ULONG) (pwszTmp - lpwszCurrentPath); // number of characters copied
  2742. // Back up pointer to the terminating NULL (we have to append here).
  2743. pwszFullPath--;
  2744. cwchFullPath--;
  2745. // If any non-NULL characters were copied, then check to make sure path ends with '\'.
  2746. if (cwchFullPath != 0)
  2747. {
  2748. if (awchFullPath[cwchFullPath - 1] != L'\\')
  2749. {
  2750. // Put in the '\' and NULL and update character count.
  2751. *pwszFullPath++ = L'\\';
  2752. *pwszFullPath = 0x0000;
  2753. cwchFullPath++;
  2754. }
  2755. // Path info was copied, so we didn't have a full path.
  2756. bFullPath = FALSE;
  2757. }
  2758. }
  2759. // Append the file name
  2760. pwszTmp = (PWSZ) lpwszFontFile;
  2761. while ( *pwszFullPath++ = *pwszTmp++ );
  2762. // Note: lengths include the NULL.
  2763. cwchFullPath += (ULONG) (pwszTmp - lpwszFontFile); // add on number of characters copied
  2764. cwchFileName = (ULONG) (pwszTmp - lpwszFontFile); // number of characters copied
  2765. // [Win 3.1 compatibility]
  2766. // Win 3.1 is paranoid. They parse the full pathname backward to look for
  2767. // filename (without path), just in case both lpwszCurrentPath and
  2768. // pwszFileName (with a path) is passed in.
  2769. // Adjust pointer to terminating NULL.
  2770. pwszFullPath--;
  2771. // Move pointer to beginning of filename alone. Figure out the length
  2772. // of just the filename.
  2773. pwszTmp = pwszFullPath;
  2774. // Note: loop terminates when beginning of string is reached or
  2775. // the first '\' is encountered.
  2776. for (cwch = cwchFullPath;
  2777. (cwch != 0) && (*pwszTmp != L'\\');
  2778. cwch--, pwszTmp--
  2779. );
  2780. pwszTmp++; // backed up one too far
  2781. cwchFileName = cwchFullPath - cwch; // cwch is length of just path
  2782. // The filename is the module name, so set the pointer at current position.
  2783. pwszModuleName = pwszTmp;
  2784. // Figure out the length of module name (filename with no extention).
  2785. // NULL is not counted (nor does it exist!).
  2786. // Note: loop terminates when end of string is reached or
  2787. // '.' is encountered.
  2788. for (cwch = 0;
  2789. (cwch < cwchFileName) && (*pwszTmp != L'.');
  2790. cwch++, pwszTmp++
  2791. );
  2792. // Truncate length to 8 because Win 3.1 does (probably an EXE format
  2793. // requirement).
  2794. cwchModuleName = min(cwch, 8);
  2795. // If a full path was passed in via pwszFileName, then set offset to it.
  2796. if ( bFullPath )
  2797. {
  2798. dpwszFullPath = 0;
  2799. }
  2800. // Otherwise, set offset to filename alone.
  2801. else
  2802. {
  2803. dpwszFullPath = (PTRDIFF)(pwszModuleName - awchFullPath); // this is win64 safe cast!
  2804. cwchFullPath = cwchFileName;
  2805. }
  2806. // Allocate memory on the stack for the Font Directory resource structure.
  2807. RtlZeroMemory((PVOID) ajFontDir, (UINT) CJ_FONTDIR);
  2808. // Call GreMakeFontDir to create a Font Directory resource.
  2809. {
  2810. UNICODE_STRING unicodeString;
  2811. PWSZ pwsz;
  2812. RtlDosPathNameToNtPathName_U(awchFullPath,
  2813. &unicodeString,
  2814. NULL,
  2815. NULL);
  2816. cjFontDir = NtGdiMakeFontDir(flEmbed,
  2817. ajFontDir,
  2818. sizeof(ajFontDir),
  2819. unicodeString.Buffer,
  2820. (unicodeString.Length + 1) * sizeof(*(unicodeString.Buffer))
  2821. );
  2822. if (unicodeString.Buffer)
  2823. {
  2824. RtlFreeHeap(RtlProcessHeap(),0,unicodeString.Buffer);
  2825. }
  2826. }
  2827. if ( cjFontDir == (ULONG ) 0 )
  2828. {
  2829. WARNING("CreateScalableFontResourceInternalW(): fontdir creation failed\n");
  2830. return (FALSE);
  2831. }
  2832. // Find the facename and facename length in the font directory.
  2833. pszTmp = (PSZ) (ajFontDir + SIZEFFH + 4 + 1);
  2834. while (*pszTmp++); // skip the family name.
  2835. pszFaceName = pszTmp;
  2836. // Note: count does not include NULL in this case.
  2837. for (cchFaceName = 0; *pszTmp; pszTmp++, cchFaceName++);
  2838. // Allocate memory on the stack for the font resource file memory image.
  2839. RtlZeroMemory((PVOID) ajOutObj, (UINT) CJ_OUTOBJ);
  2840. pjOutObj = ajOutObj;
  2841. // Copy generic EXE header into output image.
  2842. RtlCopyMemory(pjOutObj, ajExeHeader, SIZEEXEHEADER);
  2843. // Copy generic New EXE header into output image.
  2844. RtlCopyMemory(pjOutObj + SIZEEXEHEADER, ausNewExe, SIZENEWEXE);
  2845. // Copy the fake resource table into output image.
  2846. RtlCopyMemory(pjOutObj + SIZEEXEHEADER + SIZENEWEXE, ausFakeResTable, SIZEFAKERESTBL);
  2847. // Patch up field, Font Directory Size Index (as a count of aligned pages).
  2848. WRITE_WORD(pjOutObj + OFF_FONTDIRSIZINDEX, (cjFontDir + ALIGNMENTCOUNT - 1) >> ALIGNMENTSHIFT);
  2849. // Patch offsets to imported names table and module reference table.
  2850. usTmp = (USHORT) (cwchModuleName +
  2851. READ_WORD(pjOutObj + SIZEEXEHEADER + OFF_ne_restab) +
  2852. 6);
  2853. WRITE_WORD((pjOutObj + SIZEEXEHEADER + OFF_ne_imptab), usTmp);
  2854. WRITE_WORD((pjOutObj + SIZEEXEHEADER + OFF_ne_modtab), usTmp);
  2855. // Patch offset to entry table.
  2856. usTmp += (USHORT) cwchFileName + 1;
  2857. WRITE_WORD((pjOutObj + SIZEEXEHEADER + OFF_ne_enttab), usTmp);
  2858. // Patch offset to and size of non-resident name table.
  2859. usTmp += SIZEEXEHEADER + 4;
  2860. WRITE_DWORD((pjOutObj + SIZEEXEHEADER + OFF_ne_nrestab), (DWORD) usTmp);
  2861. WRITE_WORD((pjOutObj + SIZEEXEHEADER + OFF_ne_cbnrestab), SIZEFONTRES + 4 + cchFaceName);
  2862. // Now write some data after the exe headers and fake resource table.
  2863. pjOutObj += SIZEEXEHEADER + SIZENEWEXE + SIZEFAKERESTBL;
  2864. // Write out module name length and module name.
  2865. *pjOutObj++ = (BYTE) cwchModuleName; // win 3.1 assumes < 256, so will we
  2866. // Note: Writing cwchModuleName+1 characters because cwchModuleName
  2867. // does not include space for a NULL character.
  2868. vToASCIIN((PSZ) pjOutObj, (UINT) cwchModuleName + 1, pwszModuleName, (UINT) cwchModuleName + 1);
  2869. pjOutObj += cwchModuleName & 0x00ff; // enforce < 256 assumption
  2870. // Pad with 5 bytes of zeroes.
  2871. *pjOutObj++ = 0;
  2872. *pjOutObj++ = 0;
  2873. *pjOutObj++ = 0;
  2874. *pjOutObj++ = 0;
  2875. *pjOutObj++ = 0;
  2876. // Write out file name length and file name.
  2877. *pjOutObj++ = (BYTE) cwchFileName; // win 3.1 assumes < 256, so will we
  2878. vToASCIIN((PSZ) pjOutObj, (UINT) cwchFileName, pwszModuleName, (UINT) cwchFileName);
  2879. pjOutObj += cwchFileName & 0x00ff; // enforce < 256 assumption
  2880. // Pad with 4 bytes of zeroes.
  2881. *pjOutObj++ = 0;
  2882. *pjOutObj++ = 0;
  2883. *pjOutObj++ = 0;
  2884. *pjOutObj++ = 0;
  2885. // Write out size of non-resident name table and the table itself.
  2886. *pjOutObj++ = (BYTE) (SIZEFONTRES + 4 + cchFaceName);
  2887. RtlCopyMemory(pjOutObj, ajFontRes, SIZEFONTRES);
  2888. pjOutObj += SIZEFONTRES;
  2889. RtlCopyMemory(pjOutObj, pszFaceName, (UINT) cchFaceName);
  2890. pjOutObj += cchFaceName;
  2891. // Pad with 8 bytes of zeroes.
  2892. RtlZeroMemory(pjOutObj, 8);
  2893. pjOutObj += 8;
  2894. // Store some bogus code. (Just an x86 RET instruction).
  2895. pjOutObj = ajOutObj + CODE_OFFSET;
  2896. *pjOutObj++ = 0xc3; // RET OpCode.
  2897. *pjOutObj++ = 0x00;
  2898. // Copy the "full path name" into the resource position.
  2899. pjOutObj = ajOutObj + RESOURCE_OFFSET;
  2900. vToASCIIN((PSZ) pjOutObj, (UINT) cwchFullPath, awchFullPath + dpwszFullPath, (UINT) cwchFullPath);
  2901. pjOutObj += cwchFullPath;
  2902. // Pad to paragraph boundary with zeroes.
  2903. RtlZeroMemory(pjOutObj, PRIVRESSIZE - cwchFullPath);
  2904. pjOutObj += PRIVRESSIZE - cwchFullPath;
  2905. // Finally, copy the font directory.
  2906. RtlCopyMemory(pjOutObj, ajFontDir, cjFontDir);
  2907. pjOutObj += cjFontDir;
  2908. // Add add a one paragraph padding of zeroes.
  2909. RtlZeroMemory(pjOutObj, 16);
  2910. // Create the file.
  2911. if ( (hResFile = CreateFileW(lpwszResourceFile,
  2912. GENERIC_WRITE | GENERIC_READ,
  2913. FILE_SHARE_READ,
  2914. NULL,
  2915. CREATE_NEW,
  2916. FILE_ATTRIBUTE_NORMAL,
  2917. NULL)) != (HANDLE) -1 )
  2918. {
  2919. //
  2920. // Write memory image to the file.
  2921. //
  2922. ULONG cjWasWritten;
  2923. if (WriteFile(hResFile,
  2924. ajOutObj,
  2925. CJ_OUTOBJ,
  2926. (LPDWORD) &cjWasWritten,
  2927. NULL) )
  2928. {
  2929. if (CloseHandle(hResFile) != 0)
  2930. {
  2931. return (TRUE);
  2932. }
  2933. else
  2934. {
  2935. WARNING("CreateScalableFontResourceInternalW(): error closing file\n");
  2936. }
  2937. }
  2938. else
  2939. {
  2940. WARNING("CreateScalableFontResourceInternalW(): error writing to file\n");
  2941. }
  2942. //
  2943. // Close the file on error
  2944. //
  2945. CloseHandle(hResFile);
  2946. }
  2947. return (FALSE);
  2948. }
  2949. /******************************Public*Routine******************************\
  2950. * CreateScalableFontResourceW
  2951. *
  2952. * Client side stub to GreCreateScalableFontResourceW.
  2953. *
  2954. * History:
  2955. * 16-Feb-1992 -by- Gilman Wong [gilmanw]
  2956. * Wrote it.
  2957. \**************************************************************************/
  2958. BOOL APIENTRY CreateScalableFontResourceW (
  2959. DWORD flHidden, // mark file as embedded font
  2960. LPCWSTR lpwszResourceFile, // name of file to create
  2961. LPCWSTR lpwszFontFile, // name of font file to use
  2962. LPCWSTR lpwszCurrentPath) // path to font file
  2963. {
  2964. BOOL bRet = FALSE;
  2965. ULONG cjData;
  2966. ULONG cwchResourceFile;
  2967. ULONG cwchFontFile;
  2968. ULONG cwchCurrentPath;
  2969. WCHAR awchResourcePathName[MAX_PATH];
  2970. WCHAR awcPathName[MAX_PATH];
  2971. WCHAR awcFileName[MAX_PATH];
  2972. PWSZ pwszFilePart;
  2973. BOOL bMadePath;
  2974. // Parameter checking.
  2975. if ( (lpwszFontFile == (LPWSTR) NULL) ||
  2976. (lpwszResourceFile == (LPWSTR) NULL)
  2977. )
  2978. {
  2979. WARNING("gdi!CreateScalableFontResourceW(): bad parameter\n");
  2980. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2981. return (FALSE);
  2982. }
  2983. // To simplify the client server parameter validation, if lpwszCurrentPath
  2984. // is NULL, make it instead point to NULL.
  2985. if ( lpwszCurrentPath == (LPWSTR) NULL )
  2986. lpwszCurrentPath = L"";
  2987. // Need to convert paths and pathnames to full qualified paths and pathnames
  2988. // here on the client side because the "current directory" is not the same
  2989. // on the server side.
  2990. // Case 1: lpwszCurrentPath is NULL, so we want to transform lpwszFontFile
  2991. // into a fully qualified path name and keep lpwszCurrentPath NULL.
  2992. if ( *lpwszCurrentPath == L'\0' )
  2993. {
  2994. // Construct a fully qualified path name.
  2995. if (!bMakePathNameW(awcPathName, (LPWSTR) lpwszFontFile, &pwszFilePart, NULL))
  2996. {
  2997. WARNING("gdi!CreateScalableFontResourceW(): could not construct src full pathname (1)\n");
  2998. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2999. return (FALSE);
  3000. }
  3001. lpwszFontFile = awcPathName;
  3002. }
  3003. // Case 2: lpwszCurrentPath points to path of font file, so we want to make
  3004. // lpwszCurrentPath into a fully qualified path (not pathnmame) and
  3005. // lpwszFontFile into the file part of the fully qualified path NAME.
  3006. else
  3007. {
  3008. // Concatenate lpwszCurrentPath and lpwszFontFile to make a partial (maybe
  3009. // even full) path. Keep it temporarily in awcFileName.
  3010. lstrcpyW(awcFileName, lpwszCurrentPath);
  3011. if ( lpwszCurrentPath[wcslen(lpwszCurrentPath) - 1] != L'\\' )
  3012. lstrcatW(awcFileName, L"\\"); // append '\' to path if needed
  3013. lstrcatW(awcFileName, lpwszFontFile);
  3014. // Construct a fully qualified path name.
  3015. if (!bMakePathNameW(awcPathName, awcFileName, &pwszFilePart,NULL))
  3016. {
  3017. WARNING("gdi!CreateScalableFontResourceW(): could not construct src full pathname (2)\n");
  3018. GdiSetLastError(ERROR_INVALID_PARAMETER);
  3019. return (FALSE);
  3020. }
  3021. // Copy out the filename part.
  3022. lstrcpyW(awcFileName, pwszFilePart);
  3023. // Remove the filename part from the path name (so that it is now just
  3024. // a fully qualified PATH). We do this by turning the first character
  3025. // of the filename part into a NULL, effectively cutting this part off.
  3026. *pwszFilePart = L'\0';
  3027. // Change the pointers to point at our buffers.
  3028. lpwszCurrentPath = awcPathName;
  3029. lpwszFontFile = awcFileName;
  3030. }
  3031. // Convert the resource filename to a fully qualified path name.
  3032. if ( !GetFullPathNameW(lpwszResourceFile, MAX_PATH, awchResourcePathName, &pwszFilePart) )
  3033. {
  3034. WARNING("gdi!CreateScalableFontResourceW(): could not construct dest full pathname\n");
  3035. GdiSetLastError(ERROR_INVALID_PARAMETER);
  3036. return (FALSE);
  3037. }
  3038. else
  3039. {
  3040. lpwszResourceFile = awchResourcePathName;
  3041. }
  3042. return(CreateScalableFontResourceInternalW( flHidden,
  3043. lpwszResourceFile,
  3044. lpwszFontFile,
  3045. lpwszCurrentPath ));
  3046. }
  3047. /******************************Public*Routine******************************\
  3048. * GetRasterizerCaps
  3049. *
  3050. * Client side stub to GreGetRasterizerCaps.
  3051. *
  3052. * History:
  3053. * 17-Feb-1992 -by- Gilman Wong [gilmanw]
  3054. * Wrote it.
  3055. \**************************************************************************/
  3056. BOOL APIENTRY GetRasterizerCaps (
  3057. OUT LPRASTERIZER_STATUS lpraststat, // pointer to struct
  3058. IN UINT cjBytes // copy this many bytes into struct
  3059. )
  3060. {
  3061. return(NtGdiGetRasterizerCaps(lpraststat,cjBytes));
  3062. }
  3063. /******************************Public*Routine******************************\
  3064. * SetFontEnumeration *
  3065. * *
  3066. * Client side stub to GreSetFontEnumeration. *
  3067. * *
  3068. * History: *
  3069. * 09-Mar-1992 -by- Gilman Wong [gilmanw] *
  3070. * Wrote it. *
  3071. \**************************************************************************/
  3072. ULONG SetFontEnumeration(ULONG ulType)
  3073. {
  3074. return(NtGdiSetFontEnumeration(ulType));
  3075. }
  3076. /******************************Public*Routine******************************\
  3077. * vNewTextMetricWToNewTextMetric
  3078. *
  3079. * History:
  3080. * 20-Aug-1991 -by- Bodin Dresevic [BodinD]
  3081. * Wrote it.
  3082. \**************************************************************************/
  3083. static
  3084. VOID vNewTextMetricExWToNewTextMetricExA (
  3085. NEWTEXTMETRICEXA *pntmexa,
  3086. NTMW_INTERNAL *pntmi
  3087. )
  3088. {
  3089. NEWTEXTMETRICW *pntmw = &pntmi->entmw.etmNewTextMetricEx.ntmTm;
  3090. NEWTEXTMETRICA *pntma = &pntmexa->ntmTm;
  3091. pntma->tmHeight = pntmw->tmHeight ; // DWORD
  3092. pntma->tmAscent = pntmw->tmAscent ; // DWORD
  3093. pntma->tmDescent = pntmw->tmDescent ; // DWORD
  3094. pntma->tmInternalLeading = pntmw->tmInternalLeading ; // DWORD
  3095. pntma->tmExternalLeading = pntmw->tmExternalLeading ; // DWORD
  3096. pntma->tmAveCharWidth = pntmw->tmAveCharWidth ; // DWORD
  3097. pntma->tmMaxCharWidth = pntmw->tmMaxCharWidth ; // DWORD
  3098. pntma->tmWeight = pntmw->tmWeight ; // DWORD
  3099. pntma->tmOverhang = pntmw->tmOverhang ; // DWORD
  3100. pntma->tmDigitizedAspectX = pntmw->tmDigitizedAspectX ; // DWORD
  3101. pntma->tmDigitizedAspectY = pntmw->tmDigitizedAspectY ; // DWORD
  3102. pntma->tmItalic = pntmw->tmItalic ; // BYTE
  3103. pntma->tmUnderlined = pntmw->tmUnderlined ; // BYTE
  3104. pntma->tmStruckOut = pntmw->tmStruckOut ; // BYTE
  3105. pntma->ntmFlags = pntmw->ntmFlags ;
  3106. pntma->ntmSizeEM = pntmw->ntmSizeEM ;
  3107. pntma->ntmCellHeight = pntmw->ntmCellHeight ;
  3108. pntma->ntmAvgWidth = pntmw->ntmAvgWidth ;
  3109. pntma->tmPitchAndFamily = pntmw->tmPitchAndFamily ; // BYTE
  3110. pntma->tmCharSet = pntmw->tmCharSet ; // BYTE
  3111. pntma->tmFirstChar = pntmi->tmdNtmw.chFirst;
  3112. pntma->tmLastChar = pntmi->tmdNtmw.chLast ;
  3113. pntma->tmDefaultChar = pntmi->tmdNtmw.chDefault;
  3114. pntma->tmBreakChar = pntmi->tmdNtmw.chBreak;
  3115. // finally copy font signature, required by EnumFontFamiliesEx
  3116. pntmexa->ntmFontSig = pntmi->entmw.etmNewTextMetricEx.ntmFontSig;
  3117. }