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.

5259 lines
150 KiB

  1. /*****************************************************************************
  2. * Module Name: fontlink.cxx
  3. *
  4. * FontLink (EUDC) API's for NT graphics engine.
  5. *
  6. * History:
  7. *
  8. * 1-18-96 Gerrit van Wingerden Moved to kernel mode.
  9. * 1-14-96 Hideyuki Nagase Add Font Association emulation features.
  10. * 1-09-95 Hideyuki Nagase Rewrote it for new fontlink features.
  11. * 1-04-94 Hideyuki Nagase Update for Daytona fontlink.
  12. * 2-10-93 Gerrit van Wingerden Wrote it.
  13. *
  14. * Copyright (c) 1993-1999 Microsoft Corporation
  15. *****************************************************************************/
  16. #include "precomp.hxx"
  17. #ifdef FE_SB
  18. LONG lNormAngle(LONG lAngle);
  19. VOID vInitializeFontAssocStatus(VOID);
  20. #define EUDC_USER_REGISTRY_KEY \
  21. L"\\EUDC\\"
  22. #define EUDC_SYSTEM_REGISTRY_KEY \
  23. L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink"
  24. #define FONT_ASSOC_REGISTRY_KEY \
  25. L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FontAssoc"
  26. #define DEFAULT_EUDC_FONT L"EUDC.TTE"
  27. extern PFONT_ASSOC_SUB pFontAssocSubs;
  28. HSEMAPHORE ghsemEUDC1;
  29. HSEMAPHORE ghsemEUDC2;
  30. // used to signal the EUDC API's that it is okay to change EUDC link data
  31. // used to protects gappfeSysEUDC[] and gawcEUDCPath
  32. // - This mutex should be locked during referring above two values without
  33. // holding ghsemEUDC1. and updating above two data anytime.
  34. // used to protects BaseFontListHead
  35. // - This mutex should be locked during referring above list without
  36. // holding ghsemEUDC1. and updating above list anytime.
  37. LONG gcEUDCCount = 0;
  38. BOOL gbAnyLinkedFonts = FALSE;
  39. // Global variables for System EUDC.
  40. // FontLink Configuration value.
  41. ULONG ulFontLinkControl = 0L;
  42. static ULONG ulFontLinkChange = 0L;
  43. // HPFE for system EUDC font.
  44. PFE *gappfeSysEUDC[2] = { PPFENULL , PPFENULL };
  45. // Path of system EUDC font
  46. static WCHAR gawcEUDCPath[MAX_PATH+1];
  47. // QUICKLOOKUP for system EUDC font && TT System Font
  48. QUICKLOOKUP gqlEUDC;
  49. QUICKLOOKUP gqlTTSystem;
  50. // System eudc uniq number
  51. static ULONG ulSystemEUDCTimeStamp = 0;
  52. // FaceName eudc uniq number
  53. static ULONG ulFaceNameEUDCTimeStamp = 0;
  54. // Global variables for FaceName EUDC.
  55. // Count of face name links in the system
  56. static UINT gcNumLinks = 0;
  57. // Pointer to list of base font list
  58. static LIST_ENTRY BaseFontListHead = { (PLIST_ENTRY)&BaseFontListHead ,
  59. (PLIST_ENTRY)&BaseFontListHead };
  60. LIST_ENTRY NullListHead = { (PLIST_ENTRY)&NullListHead ,
  61. (PLIST_ENTRY)&NullListHead };
  62. static WCHAR gawcSystemACP[10];
  63. // Eudc Default Unicode codepoint
  64. WCHAR EudcDefaultChar = 0x30fb;
  65. RTL_QUERY_REGISTRY_TABLE SharedQueryTable[2];
  66. extern BOOL bSetupDefaultFlEntry(VOID);
  67. extern WCHAR gawcSystemDBCSFontPath[MAX_PATH];
  68. //
  69. // global EUDC debugging flags
  70. //
  71. #if DBG
  72. FLONG gflEUDCDebug = 0x0000;
  73. FLONG gflDumpDebug = 0x0000;
  74. #endif
  75. /*****************************************************************************
  76. * IsRegNameEqual (HANDLE hKey, HANDLE hKeyLink, BOOL *bIsEqual)
  77. *
  78. * Given two handles to registry keys,
  79. * return TRUE in bIsEqual if and only if the names of the paths are the same
  80. * (i.e., if the handles were created using ZwOpenKey (once without OBJ_OPENLINK
  81. * and once with), then the key is actually a symbolic link if this routine
  82. * returns FALSE in bIsEqual).
  83. *
  84. * If an error occurs (e.g., ZwQueryKey fails), this function returns the NTSTATUS.
  85. * If a memory allocation fails within this routine, this function returns 0.
  86. *
  87. * History:
  88. * 6-10-99 Donald Chinn
  89. * Wrote it.
  90. *****************************************************************************/
  91. static
  92. NTSTATUS IsRegNameEqual (HANDLE hKey,
  93. HANDLE hKeyLink,
  94. BOOL *bIsEqual)
  95. {
  96. NTSTATUS rv;
  97. PKEY_NAME_INFORMATION Buffer = NULL;
  98. PKEY_NAME_INFORMATION BufferLink = NULL;
  99. ULONG BufferSize, BufferLinkSize;
  100. *bIsEqual = FALSE;
  101. // get the size of the return buffers so that we can allocate memory for them
  102. ZwQueryKey (hKey, KeyNameInformation, NULL, 0, &BufferSize);
  103. ZwQueryKey (hKeyLink, KeyNameInformation, NULL, 0, &BufferLinkSize);
  104. // Add space for a null character for each buffer
  105. BufferSize += sizeof(WCHAR);
  106. BufferLinkSize += sizeof(WCHAR);
  107. // Round BufferSize up to the nearest multiple of sizeof(DWORD)
  108. BufferSize = ((BufferSize + sizeof(DWORD) - 1) / sizeof(DWORD)) * sizeof(DWORD);
  109. if ((Buffer = (PKEY_NAME_INFORMATION) PALLOCMEM (BufferSize + BufferLinkSize, 'flnk')) == NULL)
  110. {
  111. rv = 0;
  112. goto done;
  113. }
  114. BufferLink = (PKEY_NAME_INFORMATION) ((PBYTE) Buffer + BufferSize);
  115. if (!NT_SUCCESS(rv = ZwQueryKey (hKey, KeyNameInformation,
  116. Buffer, BufferSize, &BufferSize)))
  117. {
  118. goto done;
  119. }
  120. Buffer->Name[Buffer->NameLength / sizeof(WCHAR)] = L'\0';
  121. if (!NT_SUCCESS(rv = ZwQueryKey (hKeyLink, KeyNameInformation,
  122. BufferLink, BufferLinkSize, &BufferLinkSize)))
  123. {
  124. goto done;
  125. }
  126. BufferLink->Name[BufferLink->NameLength / sizeof(WCHAR)] = L'\0';
  127. *bIsEqual = (wcscmp (Buffer->Name, BufferLink->Name) ? FALSE : TRUE);
  128. done:
  129. if (Buffer)
  130. VFREEMEM (Buffer);
  131. return rv;
  132. }
  133. /*****************************************************************************
  134. * BOOL bNotIsKeySymbolicLink (const WCHAR *RegistryPathBuffer,
  135. * HANDLE *phKey,
  136. * HANDLE *phKeyLink,
  137. * BOOL *pbIsEqual)
  138. *
  139. * Given an absolute path name in the registry,
  140. * return TRUE if the function completed successfully and
  141. * return FALSE otherwise.
  142. *
  143. * The function also returns two handles associated with the key
  144. * as parameters. One is the handle returned from ZwOpenKey and
  145. * the other handle is the handle returned from ZwOpenKey when asked
  146. * to open it as a link.
  147. *
  148. * If the function succeeds, then pbIsEqual will contain TRUE
  149. * if the registry paths associated with the two handles are equal
  150. * (and FALSE otherwise). pbIsEqual is TRUE exactly when the
  151. * registry key is not a symbolic link.
  152. *
  153. * History:
  154. * 6-10-99 Donald Chinn
  155. * Wrote it.
  156. *****************************************************************************/
  157. static
  158. BOOL bNotIsKeySymbolicLink (const WCHAR *RegistryPathBuffer,
  159. HANDLE *phKey,
  160. HANDLE *phKeyLink,
  161. BOOL *pbIsEqual)
  162. {
  163. OBJECT_ATTRIBUTES ObjectAttributes;
  164. UNICODE_STRING EUDCSubKey;
  165. BOOL bIsEqual = FALSE;
  166. *phKey = NULL;
  167. *phKeyLink = NULL;
  168. // set up the pathname
  169. RtlInitUnicodeString(&EUDCSubKey, RegistryPathBuffer);
  170. InitializeObjectAttributes (&ObjectAttributes, &EUDCSubKey,
  171. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  172. NULL, NULL);
  173. if (!NT_SUCCESS(ZwOpenKey (phKey, KEY_ALL_ACCESS, &ObjectAttributes)))
  174. return FALSE;
  175. InitializeObjectAttributes (&ObjectAttributes, &EUDCSubKey,
  176. OBJ_CASE_INSENSITIVE | OBJ_OPENLINK | OBJ_KERNEL_HANDLE,
  177. NULL, NULL)
  178. if (!NT_SUCCESS(ZwOpenKey (phKeyLink, KEY_ALL_ACCESS, &ObjectAttributes)))
  179. return FALSE;
  180. // The key is a symbolic link exactly when the names of the keys are different
  181. if (!NT_SUCCESS(IsRegNameEqual (*phKey, *phKeyLink, pbIsEqual)))
  182. {
  183. return FALSE;
  184. }
  185. return TRUE;
  186. }
  187. /*****************************************************************************
  188. * VOID CleanUpEUDC()
  189. *
  190. * This function clean up EUDC when HYDRA shout down
  191. *
  192. * History
  193. * 8-26-98 Yung-Jen Tony Tsai
  194. * Wrote it.
  195. *****************************************************************************/
  196. VOID CleanUpEUDC()
  197. {
  198. // disable/unload system wide/facename eudc for current user.
  199. // clean up eudc links
  200. // on Hydra system, when the user/client goes away so does the gre
  201. // but the flag ulFontLinkChange is only set for FLINK_UNLOAD_FACENAME_USER
  202. // at this point. We need to set bit FLINK_UNLOAD_FACENAME_SYSTEM.
  203. SEMOBJ so(ghsemPublicPFT);
  204. PUBLIC_PFTOBJ pfto; // access the public font table
  205. ulFontLinkChange |= FLINK_UNLOAD_FACENAME_SYSTEM;
  206. GreEnableEUDC(FALSE);
  207. if (gqlEUDC.puiBits)
  208. {
  209. VFREEMEM(gqlEUDC.puiBits);
  210. gqlEUDC.puiBits = NULL;
  211. }
  212. if (gqlTTSystem.puiBits)
  213. {
  214. VFREEMEM(gqlTTSystem.puiBits);
  215. gqlTTSystem.puiBits = NULL;
  216. }
  217. // Release Font Associate allocated memory
  218. if (bFinallyInitializeFontAssocDefault)
  219. {
  220. ULONG iIndex;
  221. for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
  222. {
  223. if( (FontAssocDefaultTable[iIndex].ValidRegData) &&
  224. (FontAssocDefaultTable[iIndex].DefaultFontPathName[0] != L'\0') &&
  225. (FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] != PPFENULL) )
  226. {
  227. QUICKLOOKUP * pql;
  228. {
  229. PFEOBJ pfeo( FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] );
  230. pql = pfeo.pql();
  231. if (pql->puiBits)
  232. {
  233. VFREEMEM(pql->puiBits);
  234. pql->puiBits = NULL;
  235. }
  236. FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] = PPFENULL;
  237. }
  238. if (FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] != PPFENULL)
  239. {
  240. PFEOBJ pfeov(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL]);
  241. pql = pfeov.pql();
  242. if (pql->puiBits)
  243. {
  244. VFREEMEM(pql->puiBits);
  245. pql->puiBits = NULL;
  246. }
  247. FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] = PPFENULL;
  248. }
  249. }
  250. }
  251. for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
  252. {
  253. if( (FontAssocDefaultTable[iIndex].ValidRegData) &&
  254. (FontAssocDefaultTable[iIndex].DefaultFontPathName[0] != L'\0'))
  255. {
  256. pfto.bUnloadEUDCFont(FontAssocDefaultTable[iIndex].DefaultFontPathName);
  257. FontAssocDefaultTable[iIndex].DefaultFontPathName[0] = L'\0';
  258. }
  259. }
  260. }
  261. if (pFontAssocSubs)
  262. {
  263. VFREEMEM( pFontAssocSubs );
  264. pFontAssocSubs = NULL;
  265. }
  266. if (gbSystemDBCSFontEnabled)
  267. pfto.bUnloadEUDCFont(gawcSystemDBCSFontPath);
  268. }
  269. /*****************************************************************************
  270. * VOID PFFOBJ::vGetEUDC(PEUDCLOAD)
  271. *
  272. * This function finds requested facename PFEs
  273. *
  274. * History
  275. * 4-14-95 Hideyuki Nagase
  276. * Wrote it.
  277. *****************************************************************************/
  278. VOID PFFOBJ::vGetEUDC
  279. (
  280. PEUDCLOAD pEudcLoadData
  281. )
  282. {
  283. ASSERTGDI(pEudcLoadData != NULL,"PFFOBJ::vGetEUDC() pEudcLoadData == NULL\n");
  284. //
  285. // Initialize return buffer with NULL.
  286. //
  287. pEudcLoadData->pppfeData[PFE_NORMAL] = NULL;
  288. pEudcLoadData->pppfeData[PFE_VERTICAL] = NULL;
  289. if( pEudcLoadData->LinkedFace == NULL )
  290. {
  291. //
  292. // Linked face name is not specified. In this case if the font has 2 PFEs
  293. // we assume first entry is for Normal face, and 2nd is Verical face.
  294. //
  295. //
  296. // Fill it with normal face PFE.
  297. //
  298. pEudcLoadData->pppfeData[PFE_NORMAL] = ppfe(PFE_NORMAL);
  299. //
  300. // if this font has 2 PFEs, get 2nd PFE for vertical face. otherwise
  301. // use same PFE as normal face for Vertical face.
  302. //
  303. if( cFonts() == 2 )
  304. pEudcLoadData->pppfeData[PFE_VERTICAL] = ppfe(PFE_VERTICAL);
  305. else
  306. pEudcLoadData->pppfeData[PFE_VERTICAL] = ppfe(PFE_NORMAL);
  307. }
  308. else
  309. {
  310. //
  311. // Linked face name is specified, try to find out its PFE.
  312. //
  313. COUNT cFont;
  314. for( cFont = 0; cFont < cFonts(); cFont++ )
  315. {
  316. PFEOBJ pfeo(ppfe(cFont));
  317. PWSTR pwszEudcFace = pfeo.pwszFamilyName();
  318. ULONG iPfeOffset = PFE_NORMAL;
  319. //
  320. // Is this a vertical face ?
  321. //
  322. if( pwszEudcFace[0] == (WCHAR) L'@' )
  323. {
  324. iPfeOffset = PFE_VERTICAL;
  325. }
  326. //
  327. // Is this a face that we want ?
  328. //
  329. if(pfeo.bCheckFamilyName(pEudcLoadData->LinkedFace,1))
  330. {
  331. //
  332. // Yes....., keep it.
  333. //
  334. pEudcLoadData->pppfeData[iPfeOffset] = pfeo.ppfeGet();
  335. //
  336. // if this is a PFE for Normal face, also keep it for Vertical face.
  337. // after this, this value might be over-written by CORRRCT vertical
  338. // face's PFE.
  339. //
  340. // NOTE :
  341. // This code assume Normal face come faster than Vertical face...
  342. //
  343. if( iPfeOffset == PFE_NORMAL )
  344. {
  345. pEudcLoadData->pppfeData[PFE_VERTICAL] = pfeo.ppfeGet();
  346. }
  347. }
  348. }
  349. }
  350. }
  351. /*****************************************************************************
  352. * BOOL bValidFontLinkParameter(PWSTR,PWSTR *)
  353. *
  354. * This function make sure the linked font parameter is valid or not.
  355. *
  356. * History
  357. * 3-29-95 Hideyuki Nagase
  358. * Wrote it.
  359. *****************************************************************************/
  360. static
  361. BOOL bValidFontLinkParameter
  362. (
  363. PWSTR LinkedFontName,
  364. PWSTR *LinkedFaceName
  365. )
  366. {
  367. PWSTR lp = LinkedFontName;
  368. BOOL bFound = FALSE;
  369. *LinkedFaceName = NULL;
  370. while( *lp )
  371. {
  372. if( *lp == L',' )
  373. {
  374. if(bFound)
  375. {
  376. *LinkedFaceName = NULL;
  377. return(FALSE);
  378. }
  379. else
  380. {
  381. *LinkedFaceName = lp + 1;
  382. *lp = (WCHAR)NULL;
  383. bFound = TRUE;
  384. }
  385. }
  386. lp++;
  387. }
  388. return(TRUE);
  389. }
  390. /******************************************************************************
  391. * BOOL bComputeQuickLookup( QUICKLOOKUP *pql, FD_GLYPHSET *pfdg, BOOL bSystemEUDC )
  392. *
  393. * This routine computes a quick lookup structure from an FD_GLYPHSET structure.
  394. *
  395. * History:
  396. * 7-7-93 Gerrit van Wingerden [gerritv]
  397. * Wrote it.
  398. *****************************************************************************/
  399. #define uiMask2(X) (0xFFFFFFFF << (31-(X)))
  400. #define uiMask1(X) (0xFFFFFFFF >> (X))
  401. BOOL bComputeQuickLookup( QUICKLOOKUP *pql, PFE * pPFE, BOOL bSystemEUDC )
  402. {
  403. WCRUN *pwcrun;
  404. WCHAR wcHigh = 0x0000;
  405. WCHAR wcLow = 0xFFFF;
  406. UINT ui;
  407. // if this is not SystemEUDC and puiBits has pointer, the Lookup table
  408. // was already initialized.
  409. PFEOBJ pfeObj(pPFE);
  410. if (!pfeObj.bValid())
  411. return FALSE;
  412. if (pql == NULL)
  413. pql = pfeObj.pql();
  414. if ( !bSystemEUDC && pql->puiBits )
  415. return (TRUE);
  416. PFD_GLYPHSET pfdg;
  417. if(!(pfdg = pfeObj.pfdg()))
  418. return FALSE;
  419. pwcrun = pfdg->awcrun;
  420. // first figure out the high and low glyphs for this font
  421. for( ui = 0; ui < pfdg->cRuns; ui++ )
  422. {
  423. if( wcLow > pwcrun[ui].wcLow )
  424. {
  425. wcLow = pwcrun[ui].wcLow;
  426. }
  427. if( wcHigh < pwcrun[ui].wcLow + pwcrun[ui].cGlyphs )
  428. {
  429. wcHigh = ( pwcrun[ui].wcLow + pwcrun[ui].cGlyphs - 1 );
  430. }
  431. }
  432. (*pql).wcLow = wcLow;
  433. (*pql).wcHigh = wcHigh;
  434. // Now we need to allocate puiBits. In the case of the system EUDC font will
  435. // do this only once even though the glyph set can change dynamically. This
  436. // means we will always allocate 0xFFFF bits. If *pql.puiBits != NULL then
  437. // we assume the glyphset has been allocated before and leave it alone
  438. if( bSystemEUDC )
  439. {
  440. // see if already allocated before and if so don't allocate it again
  441. // we determine this by checking if *pql.auiBits is NULL or not
  442. // 8k * 8 = 64k, 64k glyphs
  443. // 8k == 8192
  444. if( (*pql).puiBits == NULL )
  445. {
  446. (*pql).puiBits = (UINT*)PALLOCMEM( 8192, 'flnk' );
  447. }
  448. else
  449. {
  450. RtlZeroMemory( (*pql).puiBits, 8192);
  451. }
  452. wcLow = 0;
  453. }
  454. else
  455. {
  456. (*pql).puiBits = (UINT*)PALLOCMEM((((wcHigh - wcLow + 1) + 31) / 32) * 4,'flnk');
  457. }
  458. if((*pql).puiBits == (UINT*) NULL)
  459. {
  460. WARNING("bComputeQuickLookup out of memory.\n");
  461. pfeObj.vFreepfdg();
  462. return(FALSE);
  463. }
  464. for( ui = 0; ui < pfdg->cRuns ; ui++ )
  465. {
  466. UINT uiFirst = ( pwcrun[ui].wcLow - wcLow ) / 32 ;
  467. UINT uiLast = ( pwcrun[ui].wcLow - wcLow + pwcrun[ui].cGlyphs - 1 ) / 32;
  468. if( uiFirst == uiLast)
  469. {
  470. (*pql).puiBits[uiFirst] |= uiMask2(pwcrun[ui].cGlyphs-1) >>
  471. ( ( pwcrun[ui].wcLow - wcLow ) % 32 );
  472. }
  473. else
  474. {
  475. (*pql).puiBits[uiFirst] |= uiMask1((pwcrun[ui].wcLow - wcLow)%32);
  476. for( UINT uiRun = uiFirst+1; uiRun < uiLast; uiRun++ )
  477. {
  478. (*pql).puiBits[uiRun] = 0xFFFFFFFF;
  479. }
  480. (*pql).puiBits[uiLast] |=
  481. uiMask2((pwcrun[ui].wcLow - wcLow + pwcrun[ui].cGlyphs-1)%32);
  482. }
  483. }
  484. pfeObj.vFreepfdg();
  485. return(TRUE);
  486. }
  487. /******************************************************************************
  488. * BOOL bAppendSysDirectory( WCHAR *pwcTarget, const WCHAR *pwcSource, UINT cchBufferSize )
  489. *
  490. * Given a file name in pwcSource, this function appends it to the
  491. * appropirate directory and returns it into the buffer pointed to
  492. * by pwcTarget. If the file already has a path it just copies
  493. * pwcSource to pwcTarget.
  494. *
  495. * History:
  496. * 8-30-93 Hideyuki Nagase [hideyukn]
  497. * Add code for searching path
  498. *
  499. * 3-23-93 Gerrit van Wingerden [gerritv]
  500. * Wrote it.
  501. *****************************************************************************/
  502. BOOL bAppendSysDirectory( WCHAR *pwcTarget, const WCHAR *pwcSource, UINT cchBufferSize )
  503. {
  504. WCHAR pwcTemp[MAX_PATH];
  505. // Check it is file name only or full path name
  506. if( wcschr(pwcSource,L'\\') != NULL )
  507. {
  508. WCHAR *pSystemRoot;
  509. // full path.
  510. //
  511. // Catitalize path name.
  512. // cCapString guarantees NULL termination of destination string
  513. cCapString(pwcTarget,pwcSource,cchBufferSize);
  514. // The path contains %SYSTEMROOT% ?
  515. if( (pSystemRoot = wcsstr(pwcTarget,L"%SYSTEMROOT%")) != NULL )
  516. {
  517. // Yes,
  518. //
  519. // Replace %SystemRoot%\FileName with \SystemRoot\FileName.
  520. // 012345678901
  521. pSystemRoot[0] = L'\\';
  522. wcscpy(&(pSystemRoot[11]),&(pSystemRoot[12]));
  523. }
  524. else
  525. {
  526. // if the file format is "C:\....", we appen "\??\" to make NtPath.
  527. // 0123
  528. // [note]
  529. //
  530. // for formal way... we need call RtlDosPathNameToNtPathName_U().
  531. // the function could not be called from kernel mode....
  532. //
  533. if((pwcTarget[1] == L':') && (pwcTarget[2] == L'\\'))
  534. {
  535. // keep a back up to pwcTemp.
  536. // Put "\??\" first.
  537. // Put original path.
  538. //
  539. if (FAILED(StringCchCopyW(pwcTemp, MAX_PATH, pwcTarget)) ||
  540. FAILED(StringCchCopyW(pwcTarget, cchBufferSize, L"\\??\\")) ||
  541. FAILED(StringCchCatW(pwcTarget, cchBufferSize, pwcTemp)))
  542. {
  543. WARNING("bAppendSysDirectory: target buffer too short.\n");
  544. return FALSE;
  545. }
  546. }
  547. else
  548. {
  549. WARNING("bAppenSysDirectory():Need conversion (DosPath -> NtPath)\n");
  550. }
  551. }
  552. #if DBG
  553. DbgPrint("bAppenSysDirectory():Path --> %ws\n",pwcTarget);
  554. #endif
  555. }
  556. else
  557. {
  558. // assume it is in the "fonts" directory
  559. if (FAILED(StringCchCopyW(pwcTemp, MAX_PATH, L"\\??\\")) ||
  560. FAILED(StringCchCatW(pwcTemp, MAX_PATH, USER_SHARED_DATA->NtSystemRoot)) ||
  561. FAILED(StringCchCatW(pwcTemp, MAX_PATH, L"\\fonts\\")) ||
  562. FAILED(StringCchCatW(pwcTemp, MAX_PATH, pwcSource)))
  563. {
  564. WARNING("bAppendSysDirectory: target buffer too short.\n");
  565. return FALSE;
  566. }
  567. cCapString(pwcTarget,pwcTemp,cchBufferSize);
  568. }
  569. return TRUE;
  570. }
  571. /****************************************************************************
  572. * GetUserEUDCRegistryPath(LPWSTR,USHORT)
  573. *
  574. * Get EUDC registry path for current loggedon user.
  575. *
  576. * History:
  577. * 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
  578. * Wrote it.
  579. ***************************************************************************/
  580. static
  581. NTSTATUS GetUserEUDCRegistryPath
  582. (
  583. LPWSTR UserEUDCPathBuffer,
  584. USHORT UserEUDCPathLen
  585. )
  586. {
  587. NTSTATUS status = STATUS_SUCCESS;
  588. UNICODE_STRING UserEUDCPath;
  589. UNICODE_STRING UserRegistryPath;
  590. UserEUDCPath.Length = 0;
  591. UserEUDCPath.MaximumLength = UserEUDCPathLen;
  592. UserEUDCPath.Buffer = UserEUDCPathBuffer;
  593. // Get path of CurrentUser key.
  594. if(NT_SUCCESS(RtlFormatCurrentUserKeyPath(&UserRegistryPath)))
  595. {
  596. // Build path for EUDC data
  597. status = RtlAppendUnicodeStringToString(&UserEUDCPath,&UserRegistryPath);
  598. if (NT_SUCCESS(status))
  599. status = RtlAppendUnicodeToString(&UserEUDCPath,EUDC_USER_REGISTRY_KEY);
  600. if (NT_SUCCESS(status))
  601. status = RtlAppendUnicodeToString(&UserEUDCPath,gawcSystemACP);
  602. RtlFreeUnicodeString(&UserRegistryPath);
  603. }
  604. else
  605. {
  606. WARNING("GetUserEUDCRegistryPath():RtlFormatCurrentUserKeyPath\n");
  607. // just retuen default path..
  608. status = RtlAppendUnicodeToString(&UserEUDCPath,L"\\Registry\\User\\.DEFAULT");
  609. if (NT_SUCCESS(status))
  610. status = RtlAppendUnicodeToString(&UserEUDCPath,EUDC_USER_REGISTRY_KEY);
  611. if (NT_SUCCESS(status))
  612. status = RtlAppendUnicodeToString(&UserEUDCPath,gawcSystemACP);
  613. }
  614. if (NT_SUCCESS(status))
  615. {
  616. // check if RtlAppendXXX didn't null-terminate the output string
  617. if (UserEUDCPath.Length == UserEUDCPath.MaximumLength)
  618. {
  619. WARNING("GetUserEUDCRegistryPath(): the output string is not null-terminated\n");
  620. status = STATUS_BUFFER_TOO_SMALL;
  621. }
  622. }
  623. return status;
  624. }
  625. /******************************************************************************
  626. * bWriteUserSystemEUDCRegistry(LPWSTR)
  627. *
  628. * Write system wide eudc font file path for request user.
  629. *
  630. * History:
  631. * 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
  632. * Wrote it.
  633. *****************************************************************************/
  634. static
  635. BOOL bWriteUserSystemEUDCRegistry
  636. (
  637. LPWSTR DataBuffer,
  638. USHORT DataLen
  639. )
  640. {
  641. WCHAR RegistryPathBuffer[MAX_PATH];
  642. HANDLE hKey = NULL;
  643. HANDLE hKeyLink = NULL;
  644. BOOL bIsEqual = FALSE;
  645. // Get EUDC registry path for requested user
  646. NTSTATUS NtStatus = GetUserEUDCRegistryPath(RegistryPathBuffer,sizeof(RegistryPathBuffer));
  647. if (NT_SUCCESS(NtStatus))
  648. {
  649. // if the registry entry is a symbolic link, fail the call
  650. if (bNotIsKeySymbolicLink (RegistryPathBuffer, &hKey, &hKeyLink, &bIsEqual) &&
  651. bIsEqual)
  652. {
  653. // Write registry.
  654. NtStatus = RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE,
  655. RegistryPathBuffer,
  656. L"SystemDefaultEUDCFont",
  657. REG_SZ,
  658. DataBuffer,
  659. DataLen * sizeof(WCHAR) );
  660. }
  661. else
  662. {
  663. NtStatus = (STATUS_SEVERITY_ERROR << 30); // any non-zero error is sufficient
  664. }
  665. }
  666. if (hKey)
  667. ZwClose (hKey);
  668. if (hKeyLink)
  669. ZwClose (hKeyLink);
  670. if(!NT_SUCCESS(NtStatus))
  671. {
  672. WARNING("bWriteUserSystemEUDCRegistry():fail\n");
  673. return(FALSE);
  674. }
  675. return(TRUE);
  676. }
  677. /******************************************************************************
  678. * bReadUserSystemEUDCRegistry(LPWSTR,USHORT)
  679. *
  680. * Read system wide eudc font file path for request user.
  681. *
  682. * History:
  683. * 9-Feb-1995 -by- Hideyuki Nagase [hideyukn]
  684. * Wrote it.
  685. *****************************************************************************/
  686. static
  687. BOOL bReadUserSystemEUDCRegistry
  688. (
  689. LPWSTR FilePathBuffer,
  690. USHORT FilePathLen
  691. )
  692. {
  693. WCHAR NoExpandFilePathBuffer[MAX_PATH];
  694. WCHAR RegistryPathBuffer[MAX_PATH];
  695. UNICODE_STRING FilePath;
  696. HANDLE hKey = NULL;
  697. HANDLE hKeyLink = NULL;
  698. BOOL bIsEqual = FALSE;
  699. RegistryPathBuffer[0] = NoExpandFilePathBuffer[0] = 0;
  700. FilePath.Length = 0;
  701. FilePath.MaximumLength = sizeof(NoExpandFilePathBuffer);
  702. FilePath.Buffer = NoExpandFilePathBuffer;
  703. // Get EUDC registry path for requested user
  704. NTSTATUS NtStatus = GetUserEUDCRegistryPath(RegistryPathBuffer,sizeof(RegistryPathBuffer));
  705. if (NT_SUCCESS(NtStatus))
  706. {
  707. // if the registry entry is a symbolic link, fail the call
  708. if (bNotIsKeySymbolicLink (RegistryPathBuffer, &hKey, &hKeyLink, &bIsEqual) &&
  709. bIsEqual)
  710. {
  711. SharedQueryTable[0].QueryRoutine = NULL;
  712. SharedQueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
  713. RTL_QUERY_REGISTRY_DIRECT;
  714. SharedQueryTable[0].Name = (PWSTR) L"SystemDefaultEUDCFont";
  715. SharedQueryTable[0].EntryContext = (PVOID) &FilePath;
  716. SharedQueryTable[0].DefaultType = REG_NONE;
  717. SharedQueryTable[0].DefaultData = NULL;
  718. SharedQueryTable[0].DefaultLength = 0;
  719. SharedQueryTable[1].QueryRoutine = NULL;
  720. SharedQueryTable[1].Flags = 0;
  721. SharedQueryTable[1].Name = NULL;
  722. // Read registry.
  723. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  724. RegistryPathBuffer,
  725. SharedQueryTable,
  726. NULL,
  727. NULL);
  728. }
  729. else
  730. {
  731. NtStatus = (STATUS_SEVERITY_ERROR << 30); // any non-zero error is sufficient
  732. }
  733. }
  734. if (hKey)
  735. ZwClose (hKey);
  736. if (hKeyLink)
  737. ZwClose (hKeyLink);
  738. if(!NT_SUCCESS(NtStatus) || FilePath.Length == 0)
  739. {
  740. if(NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
  741. {
  742. WCHAR *LastBackslash = NULL;
  743. //
  744. // if the user does not have EUDC\ActiveCodePage\SystemDefaultEUDCFont
  745. // key\value, we create the key and set the default value here..
  746. //
  747. // Create key.
  748. LastBackslash = wcsrchr(RegistryPathBuffer,L'\\');
  749. if(LastBackslash != NULL && _wcsicmp(LastBackslash+1,gawcSystemACP) == 0)
  750. {
  751. // Create HKEY_CURRENT_USER\EUDC key.
  752. *LastBackslash = L'\0';
  753. RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,RegistryPathBuffer);
  754. // Create HKEY_CURRENT_USER\EUDC\ActiveCodePage key.
  755. *LastBackslash = L'\\';
  756. RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE,RegistryPathBuffer);
  757. // Set value.
  758. if(bWriteUserSystemEUDCRegistry(DEFAULT_EUDC_FONT,
  759. wcslen(DEFAULT_EUDC_FONT)+1) )
  760. {
  761. //
  762. // Initialize FilePath with default.
  763. //
  764. RtlInitUnicodeString(&FilePath,DEFAULT_EUDC_FONT);
  765. }
  766. else goto ErrorReturn;
  767. }
  768. else goto ErrorReturn;
  769. }
  770. else goto ErrorReturn;
  771. }
  772. else
  773. {
  774. if (FilePath.Length == FilePath.MaximumLength)
  775. {
  776. WARNING("bReadUserSystemEUDCRegistry(): SystemDefaultEUDCFont path too long.\n");
  777. goto ErrorReturn;
  778. }
  779. }
  780. wcsncpy(FilePathBuffer,FilePath.Buffer,FilePathLen);
  781. return(TRUE);
  782. ErrorReturn:
  783. return(FALSE);
  784. }
  785. /*****************************************************************************
  786. * BOOL bKillEudcRFONTs( RFONT *prfntVictims )
  787. *
  788. * Given a linked list of EUDC RFONT this routine kills them all.
  789. *
  790. * History
  791. * 6-30-93 Gerrit van Wingerden
  792. * Wrote it.
  793. *****************************************************************************/
  794. static
  795. BOOL bKillEudcRFONTs( RFONT *prfntVictims )
  796. {
  797. PRFONT prfnt;
  798. while( (prfnt = prfntVictims ) != (PRFONT) NULL )
  799. {
  800. prfntVictims = prfntVictims->rflPDEV.prfntNext;
  801. {
  802. RFONTTMPOBJ rfloVictim(prfnt);
  803. // Need this so we can remove this from the PFF's RFONT list.
  804. PFFOBJ pffo(prfnt->pPFF);
  805. ASSERTGDI(pffo.bValid(), "gdisrv!vKillEudcRFONTs: bad HPFF");
  806. // We pass in NULL for ppdo because we've already removed it from the
  807. // PDEV list.
  808. if( !rfloVictim.bDeleteRFONT((PDEVOBJ *) NULL, &pffo))
  809. {
  810. WARNING("Unable vKillEudcRFONTs unable to delete RFONT.\n");
  811. return(FALSE);
  812. }
  813. }
  814. }
  815. return(TRUE);
  816. }
  817. /*****************************************************************************
  818. * RFONT *prfntDeactivateEudcRFONTs(PFE **)
  819. *
  820. * Tracks down all the EUDC RFONTS in the system removes them from the active
  821. * and deactive lists and puts them on a list for deletion which it then
  822. * returns to the caller.
  823. *
  824. * The public font table semaphore must be held by the caller for this to work.
  825. *
  826. * History
  827. * 23-01-95 Hideyuki Nagase
  828. * Rewrote it.
  829. *
  830. * 2-10-93 Gerrit van Wingerden
  831. * Wrote it.
  832. *****************************************************************************/
  833. static
  834. VOID vDeactivateEudcRFONTsWorker
  835. (
  836. PPFE *appfe,
  837. PPFF pPFF,
  838. RFONT **pprfntToBeKilled
  839. )
  840. {
  841. while(pPFF)
  842. {
  843. PFFOBJ pffo(pPFF);
  844. // Check if this font file is really loaded as EUDC font..
  845. if(pffo.bEUDC())
  846. {
  847. for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
  848. {
  849. PRFONT prfntNext;
  850. {
  851. RFONTTMPOBJ rflo(prfnt);
  852. prfntNext = rflo.prflPFF()->prfntNext;
  853. }
  854. if( ( prfnt->ppfe == appfe[PFE_NORMAL] ) ||
  855. ( prfnt->ppfe == appfe[PFE_VERTICAL] ) )
  856. {
  857. FLINKMESSAGE2(DEBUG_FONTLINK_UNLOAD,
  858. "Removing EUDC font %x.\n", prfnt);
  859. RFONTTMPOBJ rfo(prfnt);
  860. PDEVOBJ pdo(prfnt->hdevConsumer);
  861. PRFONT prf;
  862. // remove it from the active or inactive list
  863. if( prfnt->cSelected != 0 )
  864. {
  865. prf = pdo.prfntActive();
  866. rfo.vRemove(&prf, PDEV_LIST);
  867. pdo.prfntActive(prf);
  868. }
  869. else
  870. {
  871. prf = pdo.prfntInactive();
  872. rfo.vRemove(&prf, PDEV_LIST);
  873. pdo.prfntInactive(prf);
  874. pdo.cInactive( pdo.cInactive()-1 );
  875. }
  876. // add it to the kill list
  877. rfo.vInsert( pprfntToBeKilled, PDEV_LIST );
  878. }
  879. prfnt = prfntNext;
  880. }
  881. }
  882. pPFF = pPFF->pPFFNext;
  883. }
  884. }
  885. static
  886. RFONT *prfntDeactivateEudcRFONTs( PPFE *appfe )
  887. {
  888. RFONT *prfntToBeKilled = PRFNTNULL;
  889. FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,"Deactivating EUDC RFONTs.\n");
  890. SEMOBJ so1(ghsemPublicPFT);
  891. SEMOBJ so2(ghsemRFONTList);
  892. COUNT cBuckets;
  893. PPFF pPFF;
  894. PUBLIC_PFTOBJ pftoPublic; // access the public font table
  895. for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
  896. {
  897. if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
  898. {
  899. vDeactivateEudcRFONTsWorker( appfe, pPFF, &prfntToBeKilled );
  900. }
  901. }
  902. return(prfntToBeKilled);
  903. }
  904. /*****************************************************************************
  905. * BOOL bUnloadEudcFont( PFE ** )
  906. *
  907. * This function delete RFONTs and unload fontfile for specified PFE
  908. *
  909. * History:
  910. * 24-01-1995 -by- Hideyuki Nagase
  911. * Wrote it.
  912. *****************************************************************************/
  913. static
  914. BOOL bUnloadEudcFont( PFE **ppfe )
  915. {
  916. WCHAR awcPathBuffer[MAX_PATH + 1];
  917. PUBLIC_PFTOBJ pfto; // access the public font table
  918. PFEOBJ pfeo( ppfe[PFE_NORMAL] );
  919. PFFOBJ pffo( pfeo.pPFF() );
  920. // get font file path.
  921. if (FAILED(StringCchCopyW(awcPathBuffer, MAX_PATH + 1, pffo.pwszPathname())))
  922. {
  923. WARNING("bUnloadEudcFont: temporary buffer too short\n");
  924. return FALSE;
  925. }
  926. QUICKLOOKUP *pqlDelete;
  927. // Progress Normal face..
  928. pqlDelete = pfeo.pql();
  929. // if this is system wide eudc, won't need to free it.
  930. if( pqlDelete->puiBits != NULL )
  931. {
  932. VFREEMEM(pqlDelete->puiBits);
  933. pqlDelete->puiBits = NULL;
  934. }
  935. PFEOBJ pfeoVert( ppfe[PFE_VERTICAL] );
  936. if( pfeoVert.bValid() )
  937. {
  938. pqlDelete = pfeoVert.pql();
  939. // if this is system wide eudc, won't need to free it.
  940. if( pqlDelete->puiBits != NULL )
  941. {
  942. VFREEMEM(pqlDelete->puiBits);
  943. pqlDelete->puiBits = NULL;
  944. }
  945. }
  946. // Deactivate all RFONT for this PFE
  947. PRFONT prfntToBeKilled = prfntDeactivateEudcRFONTs( ppfe );
  948. // Kill all RFONT for this PFE
  949. if(!bKillEudcRFONTs( prfntToBeKilled ))
  950. {
  951. WARNING("bDeleteAllFlEntry():Can not kill Eudc RFONTs\n");
  952. return(FALSE);
  953. }
  954. //
  955. // Unload this font file.
  956. //
  957. // if others link are using this font file, the font
  958. // is not unloaded here. At the last link that is using
  959. // this font, it will be really unloaded.
  960. //
  961. #if DBG
  962. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  963. {
  964. DbgPrint("Unloading... %ws\n",awcPathBuffer);
  965. }
  966. #endif
  967. if(!pfto.bUnloadEUDCFont(awcPathBuffer))
  968. {
  969. #if DBG
  970. DbgPrint("bDeleteAllFlEntry():Can not unload Eudc %ws\n",awcPathBuffer);
  971. #endif
  972. return(FALSE);
  973. }
  974. return(TRUE);
  975. }
  976. /*****************************************************************************
  977. * PFLENTRY FindBaseFontEntry(const WCHAR *)
  978. *
  979. * This function scan the base font list to find specified font is already
  980. * exist or not.
  981. *
  982. * Return.
  983. * Exist - Pointer to FLENTRY strucrure.
  984. * Not exist - NULL
  985. *
  986. * History
  987. * 1-09-95 Hideyuki Nagase
  988. * Wrote it.
  989. *****************************************************************************/
  990. PFLENTRY FindBaseFontEntry
  991. (
  992. const WCHAR * BaseFontName
  993. )
  994. {
  995. PLIST_ENTRY p;
  996. PFLENTRY pFlEntry;
  997. p = BaseFontListHead.Flink;
  998. pFlEntry = NULL;
  999. while( p != &BaseFontListHead )
  1000. {
  1001. pFlEntry = CONTAINING_RECORD(p,FLENTRY,baseFontList);
  1002. #if DBG
  1003. if( gflEUDCDebug & (DEBUG_FONTLINK_INIT) )
  1004. {
  1005. DbgPrint("%ws v.s. %ws\n",BaseFontName,pFlEntry->awcFaceName);
  1006. }
  1007. #endif
  1008. //
  1009. // if this is Vertical font name, compair without '@'
  1010. //
  1011. const WCHAR * pFaceName = ( (pFlEntry->awcFaceName[0] != L'@') ? &(pFlEntry->awcFaceName[0]) :
  1012. &(pFlEntry->awcFaceName[1]) );
  1013. const WCHAR * pBaseFaceName = ( (BaseFontName[0] != L'@') ? &BaseFontName[0] :
  1014. &BaseFontName[1] );
  1015. //
  1016. // Compair font face name.
  1017. //
  1018. if( _wcsicmp(pBaseFaceName,pFaceName) == 0 )
  1019. {
  1020. //
  1021. // Find it.
  1022. //
  1023. break;
  1024. }
  1025. //
  1026. // try next.
  1027. //
  1028. p = p->Flink;
  1029. pFlEntry = NULL;
  1030. }
  1031. return(pFlEntry);
  1032. }
  1033. /*****************************************************************************
  1034. * PPFEDATA FindLinkedFontEntry(PLIST_ENTRY,PWSTR,PWSTR)
  1035. *
  1036. * This function scan the linked font list to find specified font is already
  1037. * exist or not.
  1038. *
  1039. * Return.
  1040. * Exist - Pointer to PPFEDATA strucrure.
  1041. * Not exist - NULL
  1042. *
  1043. * History
  1044. * 1-09-95 Hideyuki Nagase
  1045. * Wrote it.
  1046. *****************************************************************************/
  1047. static
  1048. PPFEDATA FindLinkedFontEntry
  1049. (
  1050. PLIST_ENTRY LinkedFontList,
  1051. const WCHAR * LinkedFontPath,
  1052. const WCHAR * LinkedFontFace
  1053. )
  1054. {
  1055. PLIST_ENTRY p;
  1056. PPFEDATA ppfeData;
  1057. p = LinkedFontList->Flink;
  1058. ppfeData = NULL;
  1059. while( p != LinkedFontList )
  1060. {
  1061. ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
  1062. //
  1063. // get PFE and PFF user object.
  1064. //
  1065. PFEOBJ pfeo( ppfeData->appfe[PFE_NORMAL] );
  1066. PFFOBJ pffo( pfeo.pPFF() );
  1067. #if DBG
  1068. if( gflEUDCDebug & (DEBUG_FONTLINK_INIT) )
  1069. {
  1070. DbgPrint("%ws v.s. %ws\n",pffo.pwszPathname(),LinkedFontPath);
  1071. }
  1072. #endif
  1073. //
  1074. // compair file path
  1075. //
  1076. if( _wcsicmp( pffo.pwszPathname() , LinkedFontPath ) == 0 )
  1077. {
  1078. //
  1079. // if facename of linked font is specified, check it also.
  1080. //
  1081. if( ((LinkedFontFace == NULL) &&
  1082. ((ppfeData->FontLinkFlag & FLINK_FACENAME_SPECIFIED) == 0)) ||
  1083. ((LinkedFontFace != NULL ) &&
  1084. ((ppfeData->FontLinkFlag & FLINK_FACENAME_SPECIFIED) != 0) &&
  1085. ((_wcsicmp(pfeo.pwszFamilyName() , LinkedFontFace))== 0)
  1086. )
  1087. )
  1088. {
  1089. //
  1090. // Find it.
  1091. //
  1092. break;
  1093. }
  1094. }
  1095. //
  1096. // try next.
  1097. //
  1098. p = p->Flink;
  1099. ppfeData = NULL;
  1100. }
  1101. return(ppfeData);
  1102. }
  1103. /*****************************************************************************\
  1104. * BOOL FindDefaultLinkedFontEntry
  1105. *
  1106. * This codepath check the passed facename is registered as Default link
  1107. * facename in Default link table. if so, keep its facename for the facename.
  1108. *
  1109. * History
  1110. * 1-14-96 Hideyuki Nagase
  1111. * Wrote it.
  1112. *****************************************************************************/
  1113. BOOL FindDefaultLinkedFontEntry
  1114. (
  1115. const WCHAR * CandidateFaceName,
  1116. const WCHAR * CandidatePathName
  1117. )
  1118. {
  1119. UINT iIndex;
  1120. for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
  1121. {
  1122. //
  1123. // Check the data can be read from registry or not.
  1124. //
  1125. if( FontAssocDefaultTable[iIndex].ValidRegData )
  1126. {
  1127. //
  1128. // Check this path is not filled.
  1129. //
  1130. if( FontAssocDefaultTable[iIndex].DefaultFontPathName[0] == L'\0' )
  1131. {
  1132. //
  1133. // Check the candidate is matched with the facename from registry.
  1134. //
  1135. if( _wcsicmp(CandidateFaceName,FontAssocDefaultTable[iIndex].DefaultFontFaceName) == 0 )
  1136. {
  1137. //
  1138. // Mark the candidate path to default table. This font file will be RE-loaded
  1139. // EUDC font file when GreEnableEUDC() was called next time.
  1140. //
  1141. if (FAILED(StringCchCopyW(FontAssocDefaultTable[iIndex].DefaultFontPathName, MAX_PATH+1, CandidatePathName)))
  1142. {
  1143. WARNING("FindDefaultLinkedFontEntry: temporary buffer too short\n");
  1144. return FALSE;
  1145. }
  1146. #if DBG
  1147. DbgPrint("GDISRV:FONTASSOC DEFAULT:%ws -> %ws\n",
  1148. FontAssocDefaultTable[iIndex].DefaultFontTypeID,
  1149. FontAssocDefaultTable[iIndex].DefaultFontPathName);
  1150. #endif
  1151. }
  1152. }
  1153. }
  1154. }
  1155. return TRUE;
  1156. }
  1157. /*****************************************************************************
  1158. * VOID vLinkEudcPFEs(PFLENTRY)
  1159. *
  1160. * This routine will find base font PFE from PFT, and set up Eudc data.
  1161. *
  1162. * History:
  1163. * 24-Jan-1995 -by- Hideyuki Nagase
  1164. * Wrote it.
  1165. ****************************************************************************/
  1166. static
  1167. VOID vLinkEudcPFEsWorker
  1168. (
  1169. PFLENTRY pFlEntry,
  1170. PPFF pPFF
  1171. )
  1172. {
  1173. while(pPFF)
  1174. {
  1175. //
  1176. // get PFF user object
  1177. //
  1178. PFFOBJ pffo(pPFF);
  1179. //
  1180. // if this font is loaded as EUDC, it can not be a BaseFont.
  1181. //
  1182. if( !pffo.bEUDC() )
  1183. {
  1184. for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
  1185. {
  1186. PFEOBJ pfeo(pffo.ppfe(c));
  1187. if( pfeo.bValid() )
  1188. {
  1189. BOOL bFound = FALSE;
  1190. PFLENTRY pFlEntrySelected = pFlEntry;
  1191. if( pFlEntrySelected )
  1192. {
  1193. bFound = pfeo.bCheckFamilyName(pFlEntrySelected->awcFaceName, 0);
  1194. }
  1195. else
  1196. {
  1197. const WCHAR * pwszAlias = NULL;
  1198. BOOL bIsFamilyNameAlias = FALSE;
  1199. pwszAlias = pfeo.pwszFamilyNameAlias(&bIsFamilyNameAlias);
  1200. bFound =
  1201. ((pFlEntrySelected = FindBaseFontEntry(pwszAlias)) != NULL);
  1202. if (!bFound && bIsFamilyNameAlias)
  1203. {
  1204. pwszAlias += (wcslen(pwszAlias) + 1);
  1205. bFound = ((pFlEntrySelected =
  1206. FindBaseFontEntry(pwszAlias)) != NULL);
  1207. }
  1208. }
  1209. if( bFound )
  1210. {
  1211. //
  1212. // set eudc list..
  1213. //
  1214. pfeo.vSetLinkedFontEntry( pFlEntrySelected );
  1215. #if DBG
  1216. if( gflEUDCDebug & DEBUG_FACENAME_EUDC )
  1217. {
  1218. PLIST_ENTRY p = pfeo.pGetLinkedFontList()->Flink;
  1219. DbgPrint("Found FaceName EUDC for %ws (%ws) is ",
  1220. pfeo.pwszFamilyName(),pffo.pwszPathname());
  1221. while( p != &(pFlEntrySelected->linkedFontListHead) )
  1222. {
  1223. PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList);
  1224. PFEOBJ pfeoTemp( ppfeData->appfe[PFE_NORMAL] );
  1225. PFFOBJ pffoTemp( pfeoTemp.pPFF() );
  1226. DbgPrint(" %ws ",pffoTemp.pwszPathname());
  1227. p = p->Flink;
  1228. }
  1229. DbgPrint("\n");
  1230. }
  1231. #endif
  1232. }
  1233. else
  1234. {
  1235. // mark the FaceNameEUDC pfe as NULL
  1236. pfeo.vSetLinkedFontEntry( NULL );
  1237. }
  1238. }
  1239. }
  1240. }
  1241. pPFF = pPFF->pPFFNext;
  1242. }
  1243. }
  1244. static
  1245. VOID vLinkEudcPFEs
  1246. (
  1247. PFLENTRY pFlEntry
  1248. )
  1249. {
  1250. #if DBG
  1251. if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
  1252. {
  1253. DbgPrint( "vLinkEudcPFEs():Linking All EUDC PFEs.\n");
  1254. }
  1255. #endif
  1256. SEMOBJ so(ghsemPublicPFT);
  1257. //
  1258. // WE HAD BETTER USE FONTHASH TO SEARCH BASE FONT'S PFF.
  1259. //
  1260. COUNT cBuckets;
  1261. PPFF pPFF;
  1262. //
  1263. // get PFT user object.
  1264. //
  1265. PUBLIC_PFTOBJ pftoPublic; // access the public font table
  1266. for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
  1267. {
  1268. if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
  1269. {
  1270. vLinkEudcPFEsWorker( pFlEntry, pPFF );
  1271. }
  1272. }
  1273. DEVICE_PFTOBJ pftoDevice; // access the public font table
  1274. for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
  1275. {
  1276. if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
  1277. {
  1278. vLinkEudcPFEsWorker( pFlEntry, pPFF );
  1279. }
  1280. }
  1281. }
  1282. /*****************************************************************************
  1283. * VOID vUnlinkEudcRFONTs( PPFE * )
  1284. *
  1285. * This routine reset RFONT that has specified linked font.
  1286. *
  1287. * History:
  1288. * 23-Jan-1995 -by- Hideyuki Nagase
  1289. * Wrote it
  1290. ****************************************************************************/
  1291. static
  1292. VOID vUnlinkEudcRFONTsWorker
  1293. (
  1294. PPFE *appfe,
  1295. PPFF pPFF
  1296. )
  1297. {
  1298. while(pPFF)
  1299. {
  1300. PFFOBJ pffo(pPFF);
  1301. // if this font is loaded as EUDC, it can not be a BaseFont.
  1302. if( !pffo.bEUDC() )
  1303. {
  1304. // Unlink Eudc from the RFONTs if it has specified Eudc..
  1305. for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
  1306. {
  1307. PRFONT prfntNext;
  1308. {
  1309. RFONTTMPOBJ rflo(prfnt);
  1310. prfntNext = rflo.prflPFF()->prfntNext;
  1311. }
  1312. // if this RFONT has Eudc font, search this Eudc..
  1313. for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
  1314. {
  1315. // Is this the Eudc RFONT that we want to remove?
  1316. if((prfnt->paprfntFaceName[ii] != NULL ) &&
  1317. (((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_NORMAL]) ||
  1318. ((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_VERTICAL])))
  1319. {
  1320. #if DBG
  1321. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1322. {
  1323. DbgPrint("Removing face name EUDC pair %x -> %x\n",
  1324. prfnt, prfnt->paprfntFaceName[ii]);
  1325. }
  1326. #endif
  1327. prfnt->paprfntFaceName[ii] = NULL;
  1328. }
  1329. }
  1330. // this RFONT's linked font array will be updated with new configuration
  1331. // when this RFONT is used again (see vInitEUDC()).
  1332. // and, if all Eudc font has been removed for this RFONT.
  1333. // the array, its pointer and other information for Eudc will be
  1334. // deleted/updated, vUnlinkEudcRFONTsAndPFEs() will be called instead
  1335. // of this.
  1336. prfnt->flEUDCState = 0;
  1337. prfnt = prfntNext;
  1338. }
  1339. }
  1340. pPFF = pPFF->pPFFNext;
  1341. }
  1342. }
  1343. static
  1344. VOID vUnlinkEudcRFONTs
  1345. (
  1346. PPFE *appfe
  1347. )
  1348. {
  1349. FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,"vUnlinkEudcRFONTs():Unlinking EUDC RFONTs.\n");
  1350. SEMOBJ so1(ghsemPublicPFT);
  1351. SEMOBJ so2(ghsemRFONTList);
  1352. COUNT cBuckets;
  1353. PPFF pPFF;
  1354. PUBLIC_PFTOBJ pftoPublic; // access the public font table
  1355. for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
  1356. {
  1357. if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
  1358. {
  1359. vUnlinkEudcRFONTsWorker(appfe,pPFF);
  1360. }
  1361. }
  1362. DEVICE_PFTOBJ pftoDevice; // access the public font table
  1363. for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
  1364. {
  1365. if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
  1366. {
  1367. vUnlinkEudcRFONTsWorker(appfe,pPFF);
  1368. }
  1369. }
  1370. }
  1371. /*****************************************************************************
  1372. * VOID vUnlinkEudcRFONTsAndPFEs(PPFE *,PFLENTRY)
  1373. *
  1374. * This routine reset RFONT and PFE structure that has specified linked font.
  1375. *
  1376. * History:
  1377. * 23-Jan-1995 -by- Hideyuki Nagase
  1378. * Wrote it
  1379. ****************************************************************************/
  1380. static
  1381. VOID vUnlinkEudcRFONTsAndPFEsWorker
  1382. (
  1383. PPFE *appfe,
  1384. PFLENTRY pFlEntry,
  1385. PPFF pPFF
  1386. )
  1387. {
  1388. while(pPFF)
  1389. {
  1390. PFFOBJ pffo(pPFF);
  1391. // if this font is loaded as EUDC, it can not be a BaseFont.
  1392. if( !pffo.bEUDC() )
  1393. {
  1394. // Unlink Eudc from the RFONTs if it has specified Eudc..
  1395. for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
  1396. {
  1397. PRFONT prfntNext;
  1398. {
  1399. RFONTTMPOBJ rflo(prfnt);
  1400. prfntNext = rflo.prflPFF()->prfntNext;
  1401. }
  1402. // if this RFONT has Eudc font, search this Eudc..
  1403. BOOL bFound = FALSE;
  1404. for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
  1405. {
  1406. // Is this the Eudc RFONT that we want to remove?
  1407. if(((prfnt->paprfntFaceName[ii]) != NULL ) &&
  1408. (((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_NORMAL]) ||
  1409. ((prfnt->paprfntFaceName[ii])->ppfe == appfe[PFE_VERTICAL])))
  1410. {
  1411. #if DBG
  1412. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1413. {
  1414. DbgPrint("Removing face name EUDC pair %x -> %x\n",
  1415. prfnt, prfnt->paprfntFaceName[ii]);
  1416. }
  1417. //
  1418. // Invalidate it for checking.
  1419. //
  1420. prfnt->paprfntFaceName[ii] = NULL;
  1421. #endif
  1422. bFound = TRUE;
  1423. break;
  1424. }
  1425. }
  1426. if( bFound )
  1427. {
  1428. #if DBG
  1429. // make sure the linked font array is really empty.
  1430. for( UINT jj = 0; jj < prfnt->uiNumLinks ; jj++ )
  1431. {
  1432. if( prfnt->paprfntFaceName[jj] != NULL )
  1433. {
  1434. DbgPrint("vUnloadEudcRFONTsAndPFEs():*** Deleteing Eudc \
  1435. array that has valid data\n");
  1436. }
  1437. }
  1438. #endif
  1439. // if the linked RFONT table was allocated, free it here
  1440. if( prfnt->paprfntFaceName != prfnt->aprfntQuickBuff )
  1441. VFREEMEM( prfnt->paprfntFaceName );
  1442. // we have no facename eudc for this RFONT.
  1443. prfnt->paprfntFaceName = NULL;
  1444. prfnt->uiNumLinks = 0;
  1445. prfnt->bFilledEudcArray = FALSE;
  1446. prfnt->ulTimeStamp = 0L;
  1447. }
  1448. prfnt->flEUDCState = 0;
  1449. prfnt = prfntNext;
  1450. }
  1451. // Unlink Eudcs from All PFEs that has Eudcs.
  1452. for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
  1453. {
  1454. PFEOBJ pfeo(pffo.ppfe(c));
  1455. if( pfeo.pGetLinkedFontEntry() == pFlEntry )
  1456. {
  1457. FLINKMESSAGE2(DEBUG_FONTLINK_UNLOAD,
  1458. "Removing face name PFE for %x (PFE)\n",pffo.ppfe(c));
  1459. pfeo.vSetLinkedFontEntry( NULL );
  1460. }
  1461. }
  1462. }
  1463. pPFF = pPFF->pPFFNext;
  1464. }
  1465. }
  1466. static
  1467. VOID vUnlinkEudcRFONTsAndPFEs
  1468. (
  1469. PPFE *appfe,
  1470. PFLENTRY pFlEntry
  1471. )
  1472. {
  1473. FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,
  1474. "vUnlinkEudcRFONTsAndPFEs():Unlinking EUDC RFONTs ans PFEs.\n");
  1475. SEMOBJ so1(ghsemPublicPFT);
  1476. SEMOBJ so2(ghsemRFONTList);
  1477. COUNT cBuckets;
  1478. PPFF pPFF;
  1479. // get PFT user object.
  1480. PUBLIC_PFTOBJ pftoPublic; // access the public font table
  1481. for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
  1482. {
  1483. if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
  1484. {
  1485. vUnlinkEudcRFONTsAndPFEsWorker(appfe,pFlEntry,pPFF);
  1486. }
  1487. }
  1488. DEVICE_PFTOBJ pftoDevice; // access the public font table
  1489. for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
  1490. {
  1491. if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
  1492. {
  1493. vUnlinkEudcRFONTsAndPFEsWorker(appfe,pFlEntry,pPFF);
  1494. }
  1495. }
  1496. }
  1497. /*****************************************************************************
  1498. * VOID vUnlinkAllEudcRFONTsAndPFEs(BOOL,BOOL)
  1499. *
  1500. * This routine reset RFONT and PFE structure that has any linked font.
  1501. *
  1502. * History:
  1503. * 23-Jan-1995 -by- Hideyuki Nagase
  1504. * Wrote it
  1505. ****************************************************************************/
  1506. static
  1507. VOID vUnlinkAllEudcRFONTsAndPFEsWorker
  1508. (
  1509. BOOL bUnlinkSystem,
  1510. BOOL bUnlinkFaceName,
  1511. PPFF pPFF
  1512. )
  1513. {
  1514. while(pPFF)
  1515. {
  1516. PFFOBJ pffo(pPFF);
  1517. // if this font is loaded as EUDC, it can not be a BaseFont.
  1518. if( !pffo.bEUDC() )
  1519. {
  1520. // Unlink Eudc from All RFONTs that has Eudc..
  1521. for( PRFONT prfnt = pffo.prfntList() ; prfnt != (PRFONT) NULL; )
  1522. {
  1523. PRFONT prfntNext;
  1524. {
  1525. RFONTTMPOBJ rflo(prfnt);
  1526. prfntNext = rflo.prflPFF()->prfntNext;
  1527. }
  1528. // if this RFONT has system wide eudc, unlink it..
  1529. if( bUnlinkSystem )
  1530. {
  1531. #if DBG
  1532. if( prfnt->prfntSysEUDC != (PRFONT) NULL )
  1533. {
  1534. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1535. {
  1536. DbgPrint("Removing system wide EUDC pair %x -> %x\n",
  1537. prfnt, prfnt->prfntSysEUDC);
  1538. }
  1539. prfnt->prfntSysEUDC = NULL;
  1540. }
  1541. #else
  1542. prfnt->prfntSysEUDC = NULL;
  1543. #endif
  1544. }
  1545. // if this RFONT has face name eudc, unlink it..
  1546. if( bUnlinkFaceName )
  1547. {
  1548. // NOTE :
  1549. //
  1550. // We will unlink the pointer to Rfont, even some of
  1551. // eudc link will valid (i.g. if we have on-bit of FONTLINK_SYSTEM in
  1552. // FontLinkChange value. the type of EUDC may not need to unlink.
  1553. // Because we should restructure the Rfonts array for following case,
  1554. // when even we want to only USER attribute EUDC....
  1555. //
  1556. // Before :
  1557. // BaseFont->FaceNameEUDC(SYS)->FaceNameEUDC(USER)->FaceNameEUDC(SYS)
  1558. //
  1559. // After :
  1560. // BaseFont -> FaceNameEUDC(SYS) -> FaceNameEUDC(SYS)
  1561. //
  1562. if( prfnt->paprfntFaceName != NULL )
  1563. {
  1564. for( UINT ii = 0 ; ii < prfnt->uiNumLinks ; ii++ )
  1565. {
  1566. #if DBG
  1567. if( prfnt->paprfntFaceName[ii] != NULL )
  1568. {
  1569. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1570. {
  1571. DbgPrint("Removing face name EUDC pair %x -> %x\n",
  1572. prfnt, prfnt->paprfntFaceName[ii]);
  1573. }
  1574. prfnt->paprfntFaceName[ii] = NULL;
  1575. }
  1576. #else
  1577. prfnt->paprfntFaceName[ii] = NULL;
  1578. #endif
  1579. }
  1580. if( prfnt->paprfntFaceName != prfnt->aprfntQuickBuff )
  1581. VFREEMEM( prfnt->paprfntFaceName );
  1582. prfnt->uiNumLinks = 0;
  1583. prfnt->paprfntFaceName = NULL;
  1584. prfnt->bFilledEudcArray = FALSE;
  1585. prfnt->ulTimeStamp = 0;
  1586. }
  1587. }
  1588. prfnt->flEUDCState = 0;
  1589. prfnt = prfntNext;
  1590. }
  1591. if( bUnlinkFaceName )
  1592. {
  1593. for( COUNT c = 0 ; c < pffo.cFonts() ; c++ )
  1594. {
  1595. PFEOBJ pfeo(pffo.ppfe(c));
  1596. #if DBG
  1597. if( pfeo.pGetLinkedFontEntry() != NULL )
  1598. {
  1599. FLINKMESSAGE2(DEBUG_FONTLINK_UNLOAD, \
  1600. "Removing face name PFE for %x (PFE)\n", \
  1601. pffo.ppfe(c));
  1602. pfeo.vSetLinkedFontEntry( NULL );
  1603. }
  1604. #else
  1605. pfeo.vSetLinkedFontEntry( NULL );
  1606. #endif
  1607. }
  1608. }
  1609. }
  1610. pPFF = pPFF->pPFFNext;
  1611. }
  1612. }
  1613. static
  1614. VOID vUnlinkAllEudcRFONTsAndPFEs
  1615. (
  1616. BOOL bUnlinkSystem,
  1617. BOOL bUnlinkFaceName
  1618. )
  1619. {
  1620. FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD,
  1621. "vUnlinkAllEudcRFONTsAndPFEs():Unlinking All EUDC RFONTs and PFEs.\n");
  1622. SEMOBJ so1(ghsemPublicPFT);
  1623. SEMOBJ so2(ghsemRFONTList);
  1624. COUNT cBuckets;
  1625. PPFF pPFF;
  1626. //
  1627. // get PFT user object.
  1628. //
  1629. PUBLIC_PFTOBJ pftoPublic; // access the public font table
  1630. for( cBuckets = 0; cBuckets < pftoPublic.cBuckets(); cBuckets++ )
  1631. {
  1632. if( (pPFF = pftoPublic.pPFF(cBuckets)) != NULL )
  1633. {
  1634. vUnlinkAllEudcRFONTsAndPFEsWorker(bUnlinkSystem,bUnlinkFaceName,pPFF);
  1635. }
  1636. }
  1637. DEVICE_PFTOBJ pftoDevice; // access the public font table
  1638. for( cBuckets = 0; cBuckets < pftoDevice.cBuckets(); cBuckets++ )
  1639. {
  1640. if( (pPFF = pftoDevice.pPFF(cBuckets)) != NULL )
  1641. {
  1642. vUnlinkAllEudcRFONTsAndPFEsWorker(bUnlinkSystem,bUnlinkFaceName,pPFF);
  1643. }
  1644. }
  1645. }
  1646. /*****************************************************************************
  1647. * BOOL bDeleteFlEntry(PWSTR,PWSTR,INT)
  1648. *
  1649. * This function delete base font and linked font pair from list.
  1650. *
  1651. * History
  1652. * 1-09-95 Hideyuki Nagase
  1653. * Wrote it.
  1654. *****************************************************************************/
  1655. static
  1656. BOOL bDeleteFlEntry
  1657. (
  1658. const WCHAR * BaseFontName,
  1659. const WCHAR * LinkedFontPathAndName,
  1660. INT iFontLinkType // FONTLINK_SYSTEM or FONTLINK_USER
  1661. )
  1662. {
  1663. PFLENTRY pFlEntry = NULL;
  1664. PPFEDATA ppfeData = NULL;
  1665. PWSTR LinkedFaceName = NULL;
  1666. WCHAR awcPathBuffer[MAX_PATH];
  1667. WCHAR LinkedFontName[LF_FACESIZE+MAX_PATH+1];
  1668. //
  1669. // Have a local copy...
  1670. //
  1671. if (FAILED(StringCchCopyW(LinkedFontName, LF_FACESIZE+MAX_PATH+1, LinkedFontPathAndName)))
  1672. {
  1673. WARNING("bDeleteFlEntry: temporary buffer too short\n");
  1674. return FALSE;
  1675. }
  1676. //
  1677. // Find ',' char from LinkedFontName
  1678. //
  1679. // Registry format :
  1680. //
  1681. // Type 1:
  1682. //
  1683. // This format is for the specified Linked font contains only 1 font resource.
  1684. // Except Vertical "@" face font, such as TrueType font (not TTC), and Vector font.
  1685. //
  1686. // BaseFontFaceName = REG_MULTI_SZ "FontPathFileName" , ...
  1687. //
  1688. // Type 2:
  1689. //
  1690. // This format is for the specified Linked font contains more than 1 font resource,
  1691. // TTC TrueType font, and Bitmap font.
  1692. //
  1693. // BaseFontFaceName = REG_MULTI_SZ "FontPathFileName,FontFaceNameInTheFile" , ...
  1694. //
  1695. // After calling ValidLinkedRegistry(), the ',' character is replaced with NULL if
  1696. // found.
  1697. //
  1698. if( !bValidFontLinkParameter(LinkedFontName,&LinkedFaceName) )
  1699. {
  1700. #if DBG
  1701. DbgPrint("Invalid Registry format - %ws\n",LinkedFontName);
  1702. #endif
  1703. return(FALSE);
  1704. }
  1705. //
  1706. // Get full path name for this font file.
  1707. //
  1708. if (!bAppendSysDirectory(awcPathBuffer, LinkedFontName, MAX_PATH))
  1709. return FALSE;
  1710. // If this file is being used as the system EUDC file then it can't be used
  1711. // as a facename EUDC file.
  1712. if( _wcsicmp(awcPathBuffer,gawcEUDCPath) == 0 )
  1713. {
  1714. #if DBG
  1715. DbgPrint("%ws can't be unload as a facename link because it is the system \
  1716. EUDC file.\n", LinkedFontName);
  1717. #endif
  1718. return(FALSE);
  1719. }
  1720. //
  1721. // Check base font list, To remove, the base font should be listed..
  1722. //
  1723. if( IsListEmpty( &BaseFontListHead ) ||
  1724. (pFlEntry = FindBaseFontEntry( BaseFontName )) == NULL )
  1725. {
  1726. //
  1727. // We can not find out this base font in current link list.
  1728. //
  1729. return(FALSE);
  1730. }
  1731. //
  1732. // The Entry for this base font is already exist....
  1733. //
  1734. #if DBG
  1735. //
  1736. // The FLENTRY should have one or more PFEDATA.
  1737. //
  1738. if( IsListEmpty( &(pFlEntry->linkedFontListHead) ) )
  1739. {
  1740. DbgPrint("This FLENTRY has no PFEDATA (%ws)\n",pFlEntry->awcFaceName);
  1741. }
  1742. #endif
  1743. //
  1744. // Scan linked font list for this base font.
  1745. // if this linked font is already listed, we do not add this.
  1746. //
  1747. if( (ppfeData = FindLinkedFontEntry( &(pFlEntry->linkedFontListHead) ,
  1748. awcPathBuffer, LinkedFaceName ) ) == NULL )
  1749. {
  1750. #if DBG
  1751. if( gflEUDCDebug & (DEBUG_FONTLINK_INIT|DEBUG_FONTLINK_LOAD|DEBUG_FACENAME_EUDC) )
  1752. {
  1753. DbgPrint("Can not find linked font %ws -> %ws\n",BaseFontName,LinkedFontName);
  1754. }
  1755. #endif
  1756. return(FALSE);
  1757. }
  1758. //
  1759. // Check we can really unload this eudc font.
  1760. //
  1761. if( ppfeData->FontLinkType == iFontLinkType )
  1762. {
  1763. //
  1764. // Now we can find out target PFEDATA.
  1765. //
  1766. //
  1767. // Remove the PFEDATA from current list.
  1768. //
  1769. RemoveEntryList( &(ppfeData->linkedFontList) );
  1770. //
  1771. // Decrement number of linked list count.
  1772. //
  1773. pFlEntry->uiNumLinks--;
  1774. //
  1775. // if there is no PFEDATA for this FLENTRY...
  1776. //
  1777. if( pFlEntry->uiNumLinks == 0 )
  1778. {
  1779. #if DBG
  1780. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1781. {
  1782. DbgPrint("Deleting FLENTRY for %ws\n",pFlEntry->awcFaceName);
  1783. }
  1784. if(!IsListEmpty(&(pFlEntry->linkedFontListHead)))
  1785. {
  1786. DbgPrint("bDeleteFlEntry():Deleting FLENTRY that has PFEDATA \
  1787. (%ws -> %ws)\n", BaseFontName,LinkedFontName);
  1788. }
  1789. #endif
  1790. //
  1791. // disable the link of this facename.
  1792. //
  1793. vUnlinkEudcRFONTsAndPFEs(ppfeData->appfe,pFlEntry);
  1794. //
  1795. // Remove this FLENTRY from BaseFontList.
  1796. //
  1797. RemoveEntryList( &(pFlEntry->baseFontList) );
  1798. //
  1799. // Free this FLENTRY.
  1800. //
  1801. VFREEMEM( pFlEntry );
  1802. //
  1803. // Decrement global base font number
  1804. //
  1805. gcNumLinks--;
  1806. //
  1807. // BaseFontList has been change, update TimeStamp
  1808. //
  1809. ulFaceNameEUDCTimeStamp++;
  1810. }
  1811. else
  1812. {
  1813. //
  1814. // disable the link of this facename Eudc.
  1815. //
  1816. vUnlinkEudcRFONTs(ppfeData->appfe);
  1817. //
  1818. // Update time stamp for this facename link.
  1819. //
  1820. pFlEntry->ulTimeStamp++;
  1821. }
  1822. //
  1823. // Unload this Eudc font.
  1824. //
  1825. if( !bUnloadEudcFont( ppfeData->appfe ) )
  1826. {
  1827. #if DBG
  1828. DbgPrint("bDeleteFlEntry():bUnloadEudcFont() fail - %ws\n",LinkedFontName);
  1829. #endif
  1830. }
  1831. #if DBG
  1832. if( gflEUDCDebug & DEBUG_FONTLINK_UNLOAD )
  1833. {
  1834. PFEOBJ pfeo(ppfeData->appfe[PFE_NORMAL]);
  1835. PFFOBJ pffo(pfeo.pPFF());
  1836. DbgPrint("Deleting PFEDATA for %ws\n",pffo.pwszPathname());
  1837. }
  1838. #endif
  1839. //
  1840. // Free this PFEDATA.
  1841. //
  1842. VFREEMEM( ppfeData );
  1843. return(TRUE);
  1844. }
  1845. else
  1846. {
  1847. return(FALSE);
  1848. }
  1849. }
  1850. /*****************************************************************************
  1851. * BOOL bAddFlEntry(const WCHAR *,const WCHAR *,INT,PFLENTRY *)
  1852. *
  1853. * This function add new base font and linked font pair into list.
  1854. *
  1855. * History
  1856. * 1-09-95 Hideyuki Nagase
  1857. * Wrote it.
  1858. *****************************************************************************/
  1859. static
  1860. BOOL bAddFlEntry
  1861. (
  1862. const WCHAR * BaseFontName,
  1863. const WCHAR * LinkedFontPathAndName,
  1864. INT iFontLinkType, // FONTLINK_SYSTEM or FONTLINK_USER
  1865. INT iPriority,
  1866. PFLENTRY *ppFlEntry
  1867. )
  1868. {
  1869. PFLENTRY pFlEntry = (PFLENTRY) NULL;
  1870. PFLENTRY tempEntry = (PFLENTRY) NULL;
  1871. PPFEDATA ppfeData = (PPFEDATA) NULL;
  1872. PWSTR LinkedFaceName = NULL;
  1873. WCHAR awcBuf[MAX_PATH + (MAX_PATH+LF_FACESIZE)];
  1874. PWSTR TempPathBuffer = awcBuf;
  1875. PWSTR LinkedFontName = &awcBuf[MAX_PATH];
  1876. BOOL bRet = FALSE;
  1877. gbAnyLinkedFonts = TRUE;
  1878. //
  1879. // if ppFlEntry is presented, initialize with NULL.
  1880. //
  1881. if( ppFlEntry != NULL )
  1882. *ppFlEntry = NULL;
  1883. //
  1884. // Have a local copy...
  1885. //
  1886. if (FAILED(StringCchCopyW(LinkedFontName, MAX_PATH + LF_FACESIZE, LinkedFontPathAndName)))
  1887. {
  1888. WARNING("bAddFlEntry: temporary buffer too short\n");
  1889. return FALSE;
  1890. }
  1891. //
  1892. // Find ',' char from LinkedFontName
  1893. //
  1894. // Registry format :
  1895. //
  1896. // Type 1:
  1897. //
  1898. // This format is for the specified Linked font contains only 1 font resource.
  1899. // Except Vertical "@" face font, such as TrueType font (not TTC), and Vector font.
  1900. //
  1901. // BaseFontFaceName = REG_MULTI_SZ "FontPathFileName" , ...
  1902. //
  1903. // Type 2:
  1904. //
  1905. // This format is for the specified Linked font contains more than 1 font resource,
  1906. // TTC TrueType font, and Bitmap font.
  1907. //
  1908. // BaseFontFaceName = REG_MULTI_SZ "FontPathFileName,FontFaceNameInTheFile" , ...
  1909. //
  1910. // After calling ValidLinkedRegistry(), the ',' character is replaced with NULL if
  1911. // found.
  1912. //
  1913. if( !bValidFontLinkParameter(LinkedFontName,&LinkedFaceName) )
  1914. {
  1915. #if DBG
  1916. DbgPrint("Invalid Registry format - %ws\n",LinkedFontName);
  1917. #endif
  1918. return bRet;
  1919. }
  1920. #if DBG
  1921. if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
  1922. {
  1923. if( LinkedFaceName )
  1924. {
  1925. DbgPrint("FontFile - %ws : FontFace - %ws\n",LinkedFontName,LinkedFaceName);
  1926. }
  1927. }
  1928. #endif
  1929. //
  1930. // Get full path name for this font file.
  1931. //
  1932. if (!bAppendSysDirectory(TempPathBuffer, LinkedFontName, MAX_PATH))
  1933. return FALSE;
  1934. //
  1935. // If this file is being used as the system EUDC file then it can't be used
  1936. // as a facename EUDC file.
  1937. //
  1938. if( _wcsicmp(TempPathBuffer,gawcEUDCPath) == 0 )
  1939. {
  1940. #if DBG
  1941. DbgPrint(
  1942. "%ws can't be load as a facename link because it is the system EUDC file.\n",
  1943. LinkedFontName
  1944. );
  1945. #endif
  1946. return bRet;
  1947. }
  1948. //
  1949. // Check base font list, it is a new one ?
  1950. //
  1951. if( !IsListEmpty( &BaseFontListHead ) &&
  1952. (pFlEntry = FindBaseFontEntry( BaseFontName )) != NULL )
  1953. {
  1954. //
  1955. // The Entry for this base font is already exist....
  1956. //
  1957. if( !IsListEmpty( &(pFlEntry->linkedFontListHead) ) )
  1958. {
  1959. //
  1960. // Scan linked font list for this base font.
  1961. // if this linked font is already listed, we do not add this.
  1962. //
  1963. if( FindLinkedFontEntry( &(pFlEntry->linkedFontListHead) ,
  1964. TempPathBuffer , LinkedFaceName ) != NULL )
  1965. {
  1966. #if DBG
  1967. DbgPrint("Dupulicate linked font - %ws\n",LinkedFontName);
  1968. #endif
  1969. return bRet;
  1970. }
  1971. }
  1972. }
  1973. {
  1974. //
  1975. // get and validate PFT user object
  1976. //
  1977. PUBLIC_PFTOBJ pfto; // access the public font table
  1978. PPFE appfeLink[2]; // temporary buffer
  1979. LONG cFonts; // count of fonts
  1980. EUDCLOAD EudcLoadData; // eudc load data
  1981. //
  1982. // parameter for PFTOBJ::bLoadFonts()
  1983. //
  1984. FLONG flParam = PFF_STATE_EUDC_FONT;
  1985. //
  1986. // Fill up EudcLoadData structure
  1987. //
  1988. EudcLoadData.pppfeData = appfeLink;
  1989. EudcLoadData.LinkedFace = LinkedFaceName;
  1990. //
  1991. // if the FontLinkType is system, it should be a Permanent font.
  1992. //
  1993. if( iFontLinkType == FONTLINK_SYSTEM )
  1994. {
  1995. flParam |= PFF_STATE_PERMANENT_FONT;
  1996. }
  1997. if( pFlEntry == NULL )
  1998. {
  1999. // Allocate new FLENTRY..
  2000. tempEntry = pFlEntry = (PFLENTRY) PALLOCNOZ( sizeof(FLENTRY), 'flnk' );
  2001. if (!pFlEntry)
  2002. {
  2003. goto FreeMemAndExit;
  2004. }
  2005. }
  2006. //
  2007. // Allocate new PFEDATA...
  2008. //
  2009. ppfeData = (PPFEDATA) PALLOCNOZ(sizeof(PFEDATA), 'flnk' );
  2010. if (!ppfeData)
  2011. {
  2012. goto FreeMemAndExit;
  2013. }
  2014. //
  2015. // Load the linked font.
  2016. //
  2017. PFF *placeHolder;
  2018. if( pfto.bLoadAFont( TempPathBuffer,
  2019. (PULONG) &cFonts,
  2020. flParam,
  2021. &placeHolder,
  2022. &EudcLoadData ) )
  2023. {
  2024. //
  2025. // Check we really succeed to load requested facename font.
  2026. //
  2027. if(!bComputeQuickLookup( NULL, appfeLink[PFE_NORMAL], FALSE ))
  2028. {
  2029. //
  2030. // Compute table for normal face
  2031. //
  2032. WARNING("Unable to compute QuickLookUp for face name link\n");
  2033. pfto.bUnloadEUDCFont(TempPathBuffer);
  2034. goto FreeMemAndExit;
  2035. }
  2036. //
  2037. // Compute table for vertical face, if vertical face font is provided,
  2038. //
  2039. if( !bComputeQuickLookup( NULL, appfeLink[PFE_VERTICAL], FALSE ))
  2040. {
  2041. WARNING("Unable to compute QuickLookUp for face name link\n");
  2042. pfto.bUnloadEUDCFont(TempPathBuffer);
  2043. goto FreeMemAndExit;
  2044. }
  2045. if (tempEntry)
  2046. {
  2047. // Initialize number of linked font count.
  2048. pFlEntry->uiNumLinks = 0;
  2049. // Initialize link time stamp
  2050. pFlEntry->ulTimeStamp = 0;
  2051. // Copy base font name to buffer.
  2052. if (FAILED(StringCchCopyW(pFlEntry->awcFaceName, LF_FACESIZE+1, BaseFontName)))
  2053. {
  2054. WARNING("bAddFlEntry: target buffer too short.\n");
  2055. pfto.bUnloadEUDCFont(TempPathBuffer);
  2056. goto FreeMemAndExit;
  2057. }
  2058. // Initialize linked font list for this base font.
  2059. InitializeListHead( &(pFlEntry->linkedFontListHead) );
  2060. // Add this entry to BaseFontList.
  2061. InsertTailList( &BaseFontListHead , &(pFlEntry->baseFontList) );
  2062. // Increment global base font number
  2063. gcNumLinks++;
  2064. // just notify new FLENTRY was allocated to caller
  2065. if( ppFlEntry != NULL )
  2066. *(PFLENTRY *)ppFlEntry = pFlEntry;
  2067. // BaseFontList has been change, update TimeStamp
  2068. ulFaceNameEUDCTimeStamp++;
  2069. }
  2070. #if DBG
  2071. if(gflEUDCDebug&(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT|DEBUG_FACENAME_EUDC))
  2072. {
  2073. DbgPrint("Allocate PFEDATA for %ws - %ws\n",BaseFontName,LinkedFontName);
  2074. }
  2075. #endif
  2076. //
  2077. // Set PFE for linked font into the structure.
  2078. //
  2079. ppfeData->appfe[PFE_NORMAL] = appfeLink[PFE_NORMAL];
  2080. ppfeData->appfe[PFE_VERTICAL] = appfeLink[PFE_VERTICAL];
  2081. //
  2082. // Set FontLinkType.
  2083. //
  2084. ppfeData->FontLinkType = iFontLinkType;
  2085. //
  2086. // Set FontLinkFlag.
  2087. //
  2088. ppfeData->FontLinkFlag = 0L;
  2089. if( EudcLoadData.LinkedFace )
  2090. ppfeData->FontLinkFlag |= FLINK_FACENAME_SPECIFIED;
  2091. //
  2092. // Incremant number of linked font count for this base face name.
  2093. //
  2094. pFlEntry->uiNumLinks++;
  2095. //
  2096. // Update time stamp
  2097. //
  2098. pFlEntry->ulTimeStamp++;
  2099. //
  2100. // add pfe for this font our list of flinks
  2101. //
  2102. if( iPriority < 0 )
  2103. {
  2104. //
  2105. // Insert end of this list.
  2106. //
  2107. InsertTailList(&(pFlEntry->linkedFontListHead),
  2108. &(ppfeData->linkedFontList) );
  2109. }
  2110. else // later if( iPriority == 0 )
  2111. {
  2112. //
  2113. // Insert top of this list.
  2114. //
  2115. InsertHeadList(&(pFlEntry->linkedFontListHead),
  2116. &(ppfeData->linkedFontList));
  2117. }
  2118. bRet = TRUE;
  2119. }
  2120. else
  2121. {
  2122. #if DBG
  2123. DbgPrint("Failed to load EUDC font - %ws\n",TempPathBuffer);
  2124. #endif
  2125. }
  2126. }
  2127. FreeMemAndExit:
  2128. if (!bRet)
  2129. {
  2130. if(tempEntry)
  2131. {
  2132. VFREEMEM(tempEntry);
  2133. }
  2134. if (ppfeData)
  2135. {
  2136. VFREEMEM(ppfeData);
  2137. }
  2138. }
  2139. return(bRet);
  2140. }
  2141. /*****************************************************************************
  2142. * BOOL bDeleteAllFlEntry(BOOL,BOOL)
  2143. *
  2144. * This function delete all linked font information including system wide eudc.
  2145. *
  2146. * History
  2147. * 1-09-95 Hideyuki Nagase
  2148. * Wrote it.
  2149. *****************************************************************************/
  2150. static
  2151. BOOL bDeleteAllFlEntry
  2152. (
  2153. BOOL bDeleteSystem,
  2154. BOOL bDeleteFaceName
  2155. )
  2156. {
  2157. BOOL bRet = TRUE;
  2158. PFEDATA **UnloadBuffer;
  2159. PFEDATA **UnloadBufferNew;
  2160. ULONG NumUnload = 0;
  2161. ULONG MaxUnload = 40;
  2162. PFE *LocalppfeSysEUDC[2] = {NULL, NULL};
  2163. //
  2164. // make sure we are the only ones changing the EUDC data
  2165. //
  2166. GreAcquireSemaphore( ghsemEUDC1 );
  2167. ASSERTGDI(gcEUDCCount >= 0, "gcEUDCCount < 0");
  2168. if (gcEUDCCount > 0)
  2169. {
  2170. //
  2171. // another EUDC API is currently in progress
  2172. //
  2173. FLINKMESSAGE(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_UNLOAD,
  2174. " another EUDC API is currently in progress. bDeleteAllFlEntry() is failed.\n");
  2175. EngSetLastError(ERROR_LOCK_FAILED);
  2176. GreReleaseSemaphore( ghsemEUDC1 );
  2177. return(FALSE);
  2178. }
  2179. UnloadBuffer = (PFEDATA **)PALLOCNOZ(sizeof(PFEDATA *) * MaxUnload, 'dueG');
  2180. if (!UnloadBuffer) {
  2181. MaxUnload = 0;
  2182. }
  2183. // disable the link of all facename and system wide eudc.
  2184. vUnlinkAllEudcRFONTsAndPFEs(bDeleteSystem,bDeleteFaceName);
  2185. // if there is no system wife eudc font.. skip it.
  2186. if( bDeleteSystem && IS_SYSTEM_EUDC_PRESENT() )
  2187. {
  2188. // Unload system wide eudc font
  2189. LocalppfeSysEUDC[PFE_NORMAL] = gappfeSysEUDC[PFE_NORMAL];
  2190. LocalppfeSysEUDC[PFE_VERTICAL] = gappfeSysEUDC[PFE_VERTICAL];
  2191. // Clear global data.
  2192. gappfeSysEUDC[PFE_NORMAL] = NULL;
  2193. gappfeSysEUDC[PFE_VERTICAL] = NULL;
  2194. gawcEUDCPath[0] = 0;
  2195. ulSystemEUDCTimeStamp++;
  2196. }
  2197. // if there is no facename eudc, just return here.
  2198. if( bDeleteFaceName && !IsListEmpty(&BaseFontListHead) )
  2199. {
  2200. COUNT NumberOfLinks = gcNumLinks;
  2201. // start to scan facename link list.
  2202. PLIST_ENTRY p = BaseFontListHead.Flink;
  2203. while( p != &BaseFontListHead )
  2204. {
  2205. PFLENTRY pFlEntry;
  2206. PLIST_ENTRY pDelete = p;
  2207. ULONG AlivePfeData = 0;
  2208. pFlEntry = CONTAINING_RECORD(pDelete,FLENTRY,baseFontList);
  2209. // if there is no linked font for this base face, try next base font.
  2210. if(IsListEmpty(&(pFlEntry->linkedFontListHead)))
  2211. {
  2212. continue;
  2213. }
  2214. // get pointer to PFEDATA list.
  2215. PLIST_ENTRY pp = pFlEntry->linkedFontListHead.Flink;
  2216. FLINKMESSAGE2((DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_UNLOAD),
  2217. "Delete %ws link\n",pFlEntry->awcFaceName);
  2218. while( pp != &(pFlEntry->linkedFontListHead) )
  2219. {
  2220. PPFEDATA ppfeData;
  2221. PLIST_ENTRY ppDelete = pp;
  2222. ppfeData = CONTAINING_RECORD(ppDelete,PFEDATA,linkedFontList);
  2223. // Check Current FontLinkChange state to see if we can really unload
  2224. // EUDC font.
  2225. if( (ppfeData->FontLinkType == FONTLINK_SYSTEM &&
  2226. ulFontLinkChange & FLINK_UNLOAD_FACENAME_SYSTEM) ||
  2227. (ppfeData->FontLinkType == FONTLINK_USER &&
  2228. ulFontLinkChange & FLINK_UNLOAD_FACENAME_USER))
  2229. {
  2230. // Remember PFE to unload font later.
  2231. if (MaxUnload == NumUnload) {
  2232. UnloadBufferNew = (PFEDATA **)PALLOCNOZ(sizeof(PFEDATA *) * MaxUnload + 10, 'dueG');
  2233. if (UnloadBufferNew) {
  2234. MaxUnload += 10;
  2235. memcpy(UnloadBufferNew, UnloadBuffer, sizeof(PFEDATA *) * NumUnload);
  2236. if (UnloadBuffer)
  2237. VFREEMEM(UnloadBuffer);
  2238. UnloadBuffer = UnloadBufferNew;
  2239. }
  2240. }
  2241. if (MaxUnload > NumUnload)
  2242. {
  2243. UnloadBuffer[NumUnload++] = ppfeData;
  2244. pp = ppDelete->Flink;
  2245. // Delete this PFEDATA from this link list
  2246. RemoveEntryList(ppDelete);
  2247. } else {
  2248. // This PFEDATA is still valid...
  2249. AlivePfeData++;
  2250. pp = ppDelete->Flink;
  2251. bRet = FALSE;
  2252. }
  2253. }
  2254. else
  2255. {
  2256. // This PFEDATA is still valid...
  2257. AlivePfeData++;
  2258. pp = ppDelete->Flink;
  2259. }
  2260. }
  2261. // next FLENTRY...
  2262. p = pDelete->Flink;
  2263. if( AlivePfeData == 0 )
  2264. {
  2265. // Delete this FLENTRY from link list
  2266. RemoveEntryList(pDelete);
  2267. // Free FLENTRY
  2268. VFREEMEM(pDelete);
  2269. // Decrement number of facename links
  2270. gcNumLinks--;
  2271. }
  2272. else
  2273. {
  2274. if( pFlEntry->uiNumLinks != AlivePfeData )
  2275. {
  2276. // Update Timestamp for this
  2277. pFlEntry->ulTimeStamp++;
  2278. // Update number of linked font.
  2279. pFlEntry->uiNumLinks = AlivePfeData;
  2280. }
  2281. }
  2282. }
  2283. if( NumberOfLinks != gcNumLinks )
  2284. {
  2285. // BaseFontList has been changed, update TimeStamp
  2286. ulFaceNameEUDCTimeStamp++;
  2287. }
  2288. if( gcNumLinks != 0 )
  2289. {
  2290. // Connect to loaded PFEs for valid FLENTRY/PFEDATA.
  2291. vLinkEudcPFEs(NULL);
  2292. }
  2293. }
  2294. GreReleaseSemaphore( ghsemEUDC1 );
  2295. // if there is no system wide eudc font.. skip it.
  2296. if( bDeleteSystem &&
  2297. ((LocalppfeSysEUDC[PFE_NORMAL] != NULL) || (LocalppfeSysEUDC[PFE_VERTICAL] != NULL)))
  2298. {
  2299. // Unload system wide eudc font
  2300. if( !bUnloadEudcFont( LocalppfeSysEUDC ) )
  2301. {
  2302. WARNING("bDeleteAllFlEntry():Can not unload system wide eudc\n");
  2303. }
  2304. }
  2305. for (ULONG i = 0; i < NumUnload; i++) {
  2306. if( !bUnloadEudcFont(UnloadBuffer[i]->appfe)) {
  2307. WARNING("bDeleteAllFlEntry():Can not unload eudc\n");
  2308. }
  2309. VFREEMEM(UnloadBuffer[i]);
  2310. }
  2311. if (UnloadBuffer)
  2312. VFREEMEM(UnloadBuffer);
  2313. return(bRet);
  2314. }
  2315. /*****************************************************************************
  2316. * NTSTATUS BuildAndLoadLinkedFontRoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
  2317. *
  2318. * This is a callback function that is called by RtlQueryRegistryValues()
  2319. *
  2320. * History
  2321. * 1-09-95 Hideyuki Nagase
  2322. * Wrote it.
  2323. *****************************************************************************/
  2324. extern "C"
  2325. NTSTATUS
  2326. BuildAndLoadLinkedFontRoutine
  2327. (
  2328. PWSTR ValueName,
  2329. ULONG ValueType,
  2330. PVOID ValueData,
  2331. ULONG ValueLength,
  2332. PVOID Context,
  2333. PVOID EntryContext
  2334. )
  2335. {
  2336. PWSTR FontPathName = (PWSTR) PALLOCNOZ((ValueLength + 1)*sizeof(WCHAR),'flnk');
  2337. if (FontPathName == NULL) {
  2338. return (STATUS_NO_MEMORY);
  2339. }
  2340. #if DBG
  2341. if( gflEUDCDebug & (DEBUG_FACENAME_EUDC|DEBUG_FONTLINK_INIT) )
  2342. {
  2343. DbgPrint("BaseFontName - %ws : LinkedFont - %ws\n",ValueName,ValueData);
  2344. }
  2345. #endif
  2346. // if this is a value for System EUDC, return here...
  2347. if(_wcsicmp(ValueName,(PWSTR)L"SystemDefaultEUDCFont") == 0)
  2348. {
  2349. goto FreeMem;
  2350. }
  2351. // Copy it to local buffer and make sure its null-termination.
  2352. RtlMoveMemory(FontPathName,ValueData,ValueLength);
  2353. FontPathName[ValueLength/sizeof(WCHAR)] = L'\0';
  2354. // Add base font and linked font pair into global list..
  2355. // Sundown: the 3rd parameter to bAddFlEntry is iFontlinkType int
  2356. if(!bAddFlEntry(ValueName,FontPathName,(INT)(ULONG_PTR)EntryContext,-1,NULL))
  2357. {
  2358. WARNING("BuildAndLoadLinkedFontRoutine():lAddFlEntry() fail\n");
  2359. }
  2360. FreeMem:
  2361. VFREEMEM(FontPathName);
  2362. // return STATUS_SUCCESS everytime,even we got error from above call, to
  2363. // get next enumuration.
  2364. return(STATUS_SUCCESS);
  2365. }
  2366. /*****************************************************************************
  2367. * NTSTATUS bAddAllFlEntryWorker(LPWSTR,INT)
  2368. *
  2369. * This function load font and build link for eudc font according to registry.
  2370. *
  2371. * History
  2372. * 1-09-95 Hideyuki Nagase
  2373. * Wrote it.
  2374. *****************************************************************************/
  2375. static
  2376. NTSTATUS bAddAllFlEntryWorker
  2377. (
  2378. const WCHAR * EUDCRegistryPath,
  2379. INT FontLinkType // FONTLINK_SYSTEM or FONTLINK_USER
  2380. )
  2381. {
  2382. NTSTATUS NtStatus;
  2383. //
  2384. // initialize/load face name eudc
  2385. //
  2386. SharedQueryTable[0].QueryRoutine = BuildAndLoadLinkedFontRoutine;
  2387. SharedQueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  2388. SharedQueryTable[0].Name = (PWSTR)NULL;
  2389. SharedQueryTable[0].EntryContext = (PVOID)(ULONG_PTR)FontLinkType;
  2390. SharedQueryTable[0].DefaultType = REG_NONE;
  2391. SharedQueryTable[0].DefaultData = NULL;
  2392. SharedQueryTable[0].DefaultLength = 0;
  2393. SharedQueryTable[1].QueryRoutine = NULL;
  2394. SharedQueryTable[1].Flags = 0;
  2395. SharedQueryTable[1].Name = (PWSTR)NULL;
  2396. //
  2397. // Enumurate registry values
  2398. //
  2399. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  2400. EUDCRegistryPath,
  2401. SharedQueryTable,
  2402. NULL,
  2403. NULL);
  2404. return(NtStatus);
  2405. }
  2406. /*****************************************************************************
  2407. * BOOL bAddAllFlEntry(BOOL,BOOL,INT)
  2408. *
  2409. * This function load font and build link for eudc font according to registry.
  2410. *
  2411. * History
  2412. * 1-09-95 Hideyuki Nagase
  2413. * Wrote it.
  2414. *****************************************************************************/
  2415. static
  2416. BOOL bAddAllFlEntry
  2417. (
  2418. BOOL bAddSystem,
  2419. BOOL bAddFaceName
  2420. )
  2421. {
  2422. NTSTATUS NtStatus;
  2423. BOOL bLoadSystem = FALSE;
  2424. WCHAR TempPathBuffer1[MAX_PATH];
  2425. WCHAR TempPathBuffer2[MAX_PATH];
  2426. TempPathBuffer1[0] = TempPathBuffer2[0] = 0;
  2427. FLINKMESSAGE(DEBUG_FONTLINK_INIT|DEBUG_FONTLINK_LOAD,
  2428. "bAddAllFlEntry():Initializing EUDC data.\n");
  2429. //
  2430. // make sure we are the only ones changing the EUDC data
  2431. //
  2432. GreAcquireSemaphore( ghsemEUDC1 );
  2433. ASSERTGDI(gcEUDCCount >= 0, "gcEUDCCount < 0");
  2434. if (gcEUDCCount > 0)
  2435. {
  2436. //
  2437. // another EUDC API is currently in progress
  2438. //
  2439. FLINKMESSAGE(DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_UNLOAD,
  2440. " another EUDC API is currently in progress. bAddAllFlEntry() is failed.\n");
  2441. EngSetLastError(ERROR_LOCK_FAILED);
  2442. GreReleaseSemaphore( ghsemEUDC1 );
  2443. return(FALSE);
  2444. }
  2445. // initialize/load the system-wide ( all face-name EUDC font )
  2446. if( bAddSystem && !IS_SYSTEM_EUDC_PRESENT() )
  2447. {
  2448. //
  2449. // read registry data for System eudc
  2450. //
  2451. if(bReadUserSystemEUDCRegistry(TempPathBuffer1, MAX_PATH))
  2452. {
  2453. PPFE appfeSysEUDC[2];
  2454. //
  2455. // Search system-wide EUDC font. if the specified registry value does not
  2456. // contain full path name.
  2457. //
  2458. // bAppendSysDirectory return TRUE, when we have to update registry data.
  2459. // otherwise return FALSE.
  2460. //
  2461. // If the Eudc file is under Windows root directory (ex. WINNT) we want to
  2462. // update registry data. because we might fail to load EUDC after user had
  2463. // change System root with Disk Administrator.
  2464. //
  2465. if (!bAppendSysDirectory(TempPathBuffer2,TempPathBuffer1, MAX_PATH))
  2466. {
  2467. WARNING("bAddAllFlEntry: buffer too short\n");
  2468. return FALSE;
  2469. }
  2470. //
  2471. // NOTE :
  2472. //
  2473. // Currently Systen wide EUDC does not support Type 1 Registry format.
  2474. // See description in bAddFlEntry().
  2475. //
  2476. //
  2477. // get and validate PFT user object
  2478. //
  2479. PUBLIC_PFTOBJ pfto; // access the public font table
  2480. ASSERTGDI (
  2481. pfto.bValid(),
  2482. "gdisrv!bAddAllFlEntry(): could not access the public font table\n"
  2483. );
  2484. {
  2485. SEMOBJ so(ghsemPublicPFT);
  2486. //
  2487. // Check this font is already loaded as Eudc font or not.
  2488. //
  2489. if( !pfto.pPFFGet(TempPathBuffer2,
  2490. wcslen(TempPathBuffer2) + 1, // cwc
  2491. 1, // cFiles
  2492. NULL, // pdv
  2493. 0, // cjDV
  2494. NULL, // pppPFE
  2495. TRUE) ) // bEudc
  2496. {
  2497. EUDCLOAD EudcLoadData;
  2498. //
  2499. // fill up EUDCLOAD structure
  2500. //
  2501. EudcLoadData.pppfeData = appfeSysEUDC;
  2502. EudcLoadData.LinkedFace = NULL;
  2503. //
  2504. // load this font as eudc font.
  2505. //
  2506. LONG cFonts; // count of fonts
  2507. PFF *placeHolder;
  2508. bLoadSystem = pfto.bLoadAFont(TempPathBuffer2,
  2509. (PULONG) &cFonts,
  2510. PFF_STATE_EUDC_FONT,
  2511. &placeHolder,
  2512. &EudcLoadData );
  2513. }
  2514. else
  2515. {
  2516. #if DBG
  2517. DbgPrint("bAddAllElEntry():%ws is loaded as EUDC already\n",
  2518. TempPathBuffer2);
  2519. #endif
  2520. bLoadSystem = FALSE;
  2521. }
  2522. }
  2523. if( bLoadSystem )
  2524. {
  2525. //
  2526. // Compute table besed on normal face
  2527. //
  2528. if(!bComputeQuickLookup( &gqlEUDC, appfeSysEUDC[PFE_NORMAL], TRUE ) )
  2529. {
  2530. WARNING("Unable to compute QuickLookUp for system EUDC\n");
  2531. //
  2532. // Unload font..
  2533. //
  2534. pfto.bUnloadEUDCFont(TempPathBuffer2);
  2535. gappfeSysEUDC[PFE_NORMAL] = NULL;
  2536. gappfeSysEUDC[PFE_VERTICAL] = NULL;
  2537. gawcEUDCPath[0] = 0;
  2538. }
  2539. else
  2540. {
  2541. //
  2542. // We believe that vertical face has same glyphset as normal face.
  2543. //
  2544. //
  2545. // Update system wide Eudc global data..
  2546. //
  2547. gappfeSysEUDC[PFE_NORMAL] = appfeSysEUDC[PFE_NORMAL];
  2548. gappfeSysEUDC[PFE_VERTICAL] = appfeSysEUDC[PFE_VERTICAL];
  2549. wcscpy(gawcEUDCPath,TempPathBuffer2);
  2550. //
  2551. // Update global eudc timestamp.
  2552. //
  2553. ulSystemEUDCTimeStamp++;
  2554. }
  2555. }
  2556. else
  2557. {
  2558. //WARNING("Failed to load system wide EUDC font.\n");
  2559. gappfeSysEUDC[PFE_NORMAL] = PPFENULL;
  2560. gappfeSysEUDC[PFE_VERTICAL] = PPFENULL;
  2561. gawcEUDCPath[0] = 0;
  2562. }
  2563. #if DBG
  2564. if( gflEUDCDebug & (DEBUG_SYSTEM_EUDC|DEBUG_FONTLINK_INIT) )
  2565. {
  2566. DbgPrint("EUDC system wide %ws hpfe is %x vert hpfe is %x\n",
  2567. gawcEUDCPath, gappfeSysEUDC[PFE_NORMAL],
  2568. gappfeSysEUDC[PFE_VERTICAL]);
  2569. }
  2570. #endif
  2571. }
  2572. }
  2573. if( bAddFaceName )
  2574. {
  2575. if( ulFontLinkChange & FLINK_LOAD_FACENAME_SYSTEM )
  2576. {
  2577. //
  2578. // Call worker function.
  2579. //
  2580. NtStatus = bAddAllFlEntryWorker(EUDC_SYSTEM_REGISTRY_KEY,FONTLINK_SYSTEM);
  2581. #if DBG
  2582. if( !NT_SUCCESS(NtStatus) )
  2583. {
  2584. WARNING1("Face name eudc is disabled (FONTLINK_SYSTEM)\n");
  2585. }
  2586. #endif
  2587. }
  2588. if( ulFontLinkChange & FLINK_LOAD_FACENAME_USER )
  2589. {
  2590. HANDLE hKey = NULL;
  2591. HANDLE hKeyLink = NULL;
  2592. BOOL bIsEqual = FALSE;
  2593. //
  2594. // Get Registry path for Eudc..
  2595. //
  2596. NtStatus = GetUserEUDCRegistryPath(TempPathBuffer1, sizeof(TempPathBuffer1));
  2597. if (NT_SUCCESS(NtStatus))
  2598. {
  2599. // if the registry entry is a symbolic link, fail the call
  2600. if (bNotIsKeySymbolicLink (TempPathBuffer1, &hKey, &hKeyLink, &bIsEqual) &&
  2601. bIsEqual)
  2602. {
  2603. //
  2604. // Call worker function.
  2605. //
  2606. NtStatus = bAddAllFlEntryWorker(TempPathBuffer1,FONTLINK_USER);
  2607. }
  2608. else
  2609. {
  2610. NtStatus = (STATUS_SEVERITY_ERROR << 30); // any non-zero error is sufficient
  2611. }
  2612. }
  2613. if (hKey)
  2614. ZwClose (hKey);
  2615. if (hKeyLink)
  2616. ZwClose (hKeyLink);
  2617. #if DBG
  2618. if( !NT_SUCCESS(NtStatus) )
  2619. {
  2620. WARNING1("Face name eudc is disabled (FONTLINK_USER)\n");
  2621. }
  2622. #endif
  2623. }
  2624. //
  2625. // Connect to loaded PFEs.
  2626. //
  2627. vLinkEudcPFEs(NULL);
  2628. }
  2629. GreReleaseSemaphore( ghsemEUDC1 );
  2630. return(TRUE);
  2631. }
  2632. /*****************************************************************************
  2633. * BOOL bInitializeEUDC(VOID)
  2634. *
  2635. * This is called once during win32k.sys initialization and initializes the
  2636. * system EUDC information. First it creates a FLINKOBJ and set ghflEUDC to
  2637. * it. Then it initializes the FLINKOBJ with information from the registry.
  2638. * After that it loads all the EUDC fonts and sets up links between base
  2639. * font PFE's and EUDC font pfe's.
  2640. *
  2641. * History
  2642. * 1-09-95 Hideyuki Nagase
  2643. * Rewrote it.
  2644. *
  2645. * 2-10-93 Gerrit van Wingerden
  2646. * Wrote it.
  2647. *****************************************************************************/
  2648. BOOL bInitializeEUDC(VOID)
  2649. {
  2650. NTSTATUS NtStatus;
  2651. FLINKMESSAGE(DEBUG_FONTLINK_INIT,
  2652. "bInitializeEUDC():Initializing EUDC data.\n");
  2653. gawcEUDCPath[0] = L'\0';
  2654. // Set up Global EUDC semaphores
  2655. if ( !(ghsemEUDC1 = GreCreateSemaphore()))
  2656. {
  2657. return FALSE;
  2658. }
  2659. if ( !(ghsemEUDC2 = GreCreateSemaphore()))
  2660. {
  2661. return FALSE;
  2662. }
  2663. // KeInitializeEvent( &gfmEUDC2, SynchronizationEvent, FALSE );
  2664. // Set up EUDC QUICKLOOKUP Table
  2665. gqlEUDC.puiBits = NULL;
  2666. gqlEUDC.wcLow = 1;
  2667. gqlEUDC.wcHigh = 0;
  2668. // Get Current codepage to access registry..
  2669. USHORT usACP,usOEMCP;
  2670. EngGetCurrentCodePage(&usOEMCP,&usACP);
  2671. // Convert Integer to Unicode string..
  2672. UNICODE_STRING SystemACPString;
  2673. SystemACPString.Length = 0;
  2674. SystemACPString.MaximumLength = sizeof(gawcSystemACP);
  2675. SystemACPString.Buffer = gawcSystemACP;
  2676. RtlIntegerToUnicodeString( (int) usACP, 10, &SystemACPString );
  2677. FLINKMESSAGE2(DEBUG_FONTLINK_INIT,"GDISRV:System ACP is %ws\n",gawcSystemACP);
  2678. // Read FontLink configuration value.
  2679. SharedQueryTable[0].QueryRoutine = NULL;
  2680. SharedQueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
  2681. RTL_QUERY_REGISTRY_DIRECT;
  2682. SharedQueryTable[0].Name = (PWSTR)L"FontLinkControl";
  2683. SharedQueryTable[0].EntryContext = (PVOID) &ulFontLinkControl;
  2684. SharedQueryTable[0].DefaultType = REG_DWORD;
  2685. SharedQueryTable[0].DefaultData = 0;
  2686. SharedQueryTable[0].DefaultLength = 0;
  2687. SharedQueryTable[1].QueryRoutine = NULL;
  2688. SharedQueryTable[1].Flags = 0;
  2689. SharedQueryTable[1].Name = (PWSTR)NULL;
  2690. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  2691. L"FontLink",
  2692. SharedQueryTable,
  2693. NULL,
  2694. NULL);
  2695. if(!NT_SUCCESS(NtStatus))
  2696. {
  2697. // WARNING("Error reading FontLinkControl\n");
  2698. ulFontLinkControl = 0L;
  2699. }
  2700. FLINKMESSAGE2(DEBUG_FONTLINK_CONTROL,
  2701. "win32ksys:FontLinkControl = %x\n",ulFontLinkControl);
  2702. // initialize Eudc default char code in Unicode.
  2703. DWORD dwEudcDefaultChar;
  2704. SharedQueryTable[0].Name = (PWSTR)L"FontLinkDefaultChar";
  2705. SharedQueryTable[0].EntryContext = (PVOID) &dwEudcDefaultChar;
  2706. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  2707. L"FontLink",
  2708. SharedQueryTable,
  2709. NULL,
  2710. NULL);
  2711. if(!NT_SUCCESS(NtStatus))
  2712. {
  2713. // WARNING("Error reading FontLinkDefaultChar\n");
  2714. EudcDefaultChar = 0x30fb;
  2715. }
  2716. else
  2717. {
  2718. EudcDefaultChar = (WCHAR)dwEudcDefaultChar;
  2719. }
  2720. // initialize base font list
  2721. InitializeListHead(&BaseFontListHead);
  2722. // if FontLink feature is disabled, nothing to do.....
  2723. if( ulFontLinkControl & FLINK_DISABLE_FONTLINK )
  2724. {
  2725. return TRUE;
  2726. }
  2727. // Load and setup SYSTEM Global facename EUDC data.
  2728. ulFontLinkChange = FLINK_LOAD_FACENAME_SYSTEM |
  2729. FLINK_UNLOAD_FACENAME_SYSTEM;
  2730. // Enable only FaceName (system common) EUDC.
  2731. bAddAllFlEntry(FALSE,TRUE);
  2732. // After load system global EUDC, we will only allow to user to
  2733. // load/unload per user eudc configuration.
  2734. ulFontLinkChange = FLINK_LOAD_FACENAME_USER |
  2735. FLINK_UNLOAD_FACENAME_USER;
  2736. // Initialize font association scheme.
  2737. vInitializeFontAssocStatus();
  2738. return TRUE;
  2739. }
  2740. /*****************************************************************************\
  2741. * GreEnableEUDC( BOOL bEnable )
  2742. *
  2743. * This routine enable/disable system wide/face name specific EUDCs
  2744. *
  2745. * History:
  2746. * 23-Jan-1995 Hideyuki Nagase
  2747. * Wrote it.
  2748. *****************************************************************************/
  2749. BOOL GreEnableEUDC
  2750. (
  2751. BOOL bEnableEUDC
  2752. )
  2753. {
  2754. BOOL bRet = TRUE;
  2755. //
  2756. // This quick check for non-zero ghsemEUDC1 is a work around for hydra
  2757. // cleanup assertions
  2758. //
  2759. if (!ghsemEUDC1 || !ghsemEUDC2)
  2760. {
  2761. return TRUE;
  2762. }
  2763. GreAcquireSemaphore( ghsemEUDC2 );
  2764. if( bEnableEUDC )
  2765. {
  2766. //
  2767. // if DefaultLink is ready to initalize and its is not initialized,
  2768. // do the initialization.
  2769. //
  2770. if( (bReadyToInitializeFontAssocDefault == TRUE ) &&
  2771. (bFinallyInitializeFontAssocDefault == FALSE) )
  2772. {
  2773. //
  2774. // Load default linked font and fill up nessesary data fields.
  2775. //
  2776. if( bSetupDefaultFlEntry()) {
  2777. //
  2778. // Yes, we finally initialized default link font successfully.
  2779. //
  2780. bFinallyInitializeFontAssocDefault = TRUE;
  2781. }
  2782. }
  2783. }
  2784. if( bEnableEUDC )
  2785. {
  2786. //
  2787. // Enable EUDC link.
  2788. //
  2789. bRet = bAddAllFlEntry(TRUE,TRUE);
  2790. }
  2791. else
  2792. {
  2793. // Disable EUDC link.
  2794. bRet = bDeleteAllFlEntry(TRUE,TRUE);
  2795. }
  2796. GreReleaseSemaphore( ghsemEUDC2 );
  2797. return(bRet);
  2798. }
  2799. /*****************************************************************************\
  2800. * GreEudcLoadLinkW(LPWSTR,COUNT,LPWSTR,COUNT,INT,INT)
  2801. *
  2802. * Establishes a font file as the source of EUDC glyphs for the system. Any
  2803. * subsequent TextOut or GetTextMetrics related calls will reflect this
  2804. * change immediately.
  2805. *
  2806. * History:
  2807. * 13-01-95 Hideyuki Nagase
  2808. * Rewrote it.
  2809. * 02-10-93 Gerrit van Wingerden
  2810. * Wrote it.
  2811. *****************************************************************************/
  2812. static
  2813. BOOL GreEudcLoadLinkW
  2814. (
  2815. const WCHAR * lpBaseFaceName, // guaranteed to be NULL terminated
  2816. COUNT cwcBaseFaceName,
  2817. const WCHAR * lpEudcFontPath, // guaranteed to be NULL terminated
  2818. COUNT cwcEudcFontPath,
  2819. INT iPriority,
  2820. INT iFontLinkType
  2821. )
  2822. {
  2823. BOOL bRet = TRUE;
  2824. ASSERTGDI(lpEudcFontPath != NULL,"GreEudcLoadLinkW():lpEudcFontPath == NULL\n");
  2825. ASSERTGDI(cwcEudcFontPath != 0,"GreEudcLoadLinkW():cwcEudcFontPath == 0\n");
  2826. FLINKMESSAGE(DEBUG_FONTLINK_LOAD,"GreEudcLoadLinkW\n");
  2827. GreAcquireSemaphore( ghsemEUDC1 );
  2828. //
  2829. // if text related API's using EUDC characters are in progess we must
  2830. // wait
  2831. //
  2832. ASSERTGDI(gcEUDCCount >= 0, "gcEUDCCount < 0");
  2833. if (gcEUDCCount > 0)
  2834. {
  2835. #if DBG
  2836. if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
  2837. {
  2838. DbgPrint("GreEudcLoadLinkW is waiting.\n");
  2839. }
  2840. #endif
  2841. // When the last text related API using EUDC characters finishes it will
  2842. // release us.
  2843. EngSetLastError(ERROR_LOCK_FAILED);
  2844. GreReleaseSemaphore( ghsemEUDC1 );
  2845. return (FALSE);
  2846. }
  2847. // Is this a request to load system wide eudc ?
  2848. if( lpBaseFaceName == NULL )
  2849. {
  2850. WCHAR awcSystemEudcPath[MAX_PATH+1];
  2851. PPFE appfeNew[2];
  2852. // Get full path name of the requested font..
  2853. bRet = bAppendSysDirectory( awcSystemEudcPath , lpEudcFontPath, MAX_PATH );
  2854. if (bRet)
  2855. {
  2856. SEMOBJ so(ghsemPublicPFT);
  2857. // Get and validate PFT user object
  2858. PUBLIC_PFTOBJ pfto;
  2859. ASSERTGDI(pfto.bValid(),
  2860. "GreLoadLinkW():could not access the public font table\n");
  2861. // check this font file is loaded as eudc already.
  2862. if( !pfto.pPFFGet(awcSystemEudcPath,
  2863. wcslen(awcSystemEudcPath) + 1, // cwc
  2864. 1, // cFiles
  2865. NULL, // pdv
  2866. 0, // cjDV
  2867. NULL, // pppPFF
  2868. TRUE) ) // bEudc
  2869. {
  2870. EUDCLOAD EudcLoadData;
  2871. // fill up EUDCLOAD structure
  2872. EudcLoadData.pppfeData = appfeNew;
  2873. EudcLoadData.LinkedFace = NULL;
  2874. // load font..
  2875. ULONG cFonts;
  2876. PFF *placeHolder;
  2877. bRet = pfto.bLoadAFont( awcSystemEudcPath,
  2878. (PULONG) &cFonts,
  2879. PFF_STATE_EUDC_FONT,
  2880. &placeHolder,
  2881. &EudcLoadData);
  2882. }
  2883. else
  2884. {
  2885. //
  2886. // this font file is already loaded as EUDC..
  2887. //
  2888. #if DBG
  2889. DbgPrint("GreLoadLinkW():%ws is loaded as EUDC already\n",
  2890. awcSystemEudcPath);
  2891. #endif
  2892. bRet = FALSE;
  2893. }
  2894. }
  2895. if( bRet )
  2896. {
  2897. //
  2898. // now we can load new system wide eudc font..
  2899. // if we have system wide eudc font, deactivate and unload it..
  2900. //
  2901. if( IS_SYSTEM_EUDC_PRESENT() )
  2902. {
  2903. //
  2904. // disable the link of all facename and system wide eudc.
  2905. //
  2906. vUnlinkAllEudcRFONTsAndPFEs(TRUE,FALSE);
  2907. //
  2908. // Unload system wide eudc font
  2909. //
  2910. bUnloadEudcFont( gappfeSysEUDC );
  2911. }
  2912. //
  2913. // set new system wide eudc data to global variable.
  2914. //
  2915. gappfeSysEUDC[PFE_NORMAL] = appfeNew[PFE_NORMAL];
  2916. gappfeSysEUDC[PFE_VERTICAL] = appfeNew[PFE_VERTICAL];
  2917. wcscpy(gawcEUDCPath,awcSystemEudcPath);
  2918. //
  2919. // Update global eudc timestamp.
  2920. //
  2921. ulSystemEUDCTimeStamp++;
  2922. //
  2923. // Finally compute the QuickLookup structure for the system EUDC font
  2924. //
  2925. if(!bComputeQuickLookup( &gqlEUDC, appfeNew[PFE_NORMAL], TRUE ))
  2926. {
  2927. WARNING("GreLoadLinkW:Unable to compute QuickLookUp for system EUDC\n");
  2928. }
  2929. //
  2930. //
  2931. // Update registry data.
  2932. //
  2933. FLINKMESSAGE(DEBUG_FONTLINK_LOAD,"GreLoadLinkW():Eudc Path %ws is Saved\n");
  2934. if( !bWriteUserSystemEUDCRegistry(gawcEUDCPath, wcslen(gawcEUDCPath)+1) )
  2935. {
  2936. WARNING("Unable to write new link to registry.\n");
  2937. }
  2938. }
  2939. else
  2940. {
  2941. //
  2942. // Fail to load ...
  2943. //
  2944. #if DBG
  2945. DbgPrint("GreLoadLinkW():%ws is could not be loaded\n",awcSystemEudcPath);
  2946. #endif
  2947. }
  2948. }
  2949. else
  2950. {
  2951. PFLENTRY pFlEntry;
  2952. //
  2953. // if we got invalid fontlink type, just force change to FONTLINK_USER
  2954. //
  2955. if( (iFontLinkType != FONTLINK_SYSTEM) &&
  2956. (iFontLinkType != FONTLINK_USER ) )
  2957. {
  2958. iFontLinkType = FONTLINK_USER;
  2959. }
  2960. //
  2961. // this is request for facename link.
  2962. //
  2963. bRet = bAddFlEntry(lpBaseFaceName,lpEudcFontPath,iFontLinkType,iPriority,
  2964. &pFlEntry);
  2965. if( bRet )
  2966. {
  2967. //
  2968. // check new FLENTRY is allocated or not.
  2969. //
  2970. if( pFlEntry != NULL )
  2971. {
  2972. //
  2973. // if new FLENTRY is allocated, Update base font's PFE.
  2974. // Connect to loaded PFEs.
  2975. //
  2976. vLinkEudcPFEs( pFlEntry );
  2977. }
  2978. }
  2979. }
  2980. GreReleaseSemaphore( ghsemEUDC1 );
  2981. return(bRet);
  2982. }
  2983. /*****************************************************************************
  2984. * GreEudcUnloadLinkW()
  2985. *
  2986. * Unloads the current system wide EUDC link. Subsequent TextOut or
  2987. * GetTextMetrics related calls will reflect this immediately.
  2988. *
  2989. * History
  2990. * 26-01-95 Hideyuki Nagase
  2991. * Rewrote it.
  2992. * 4-01-93 Gerrit van Wingerden
  2993. * Wrote it.
  2994. *****************************************************************************/
  2995. static
  2996. BOOL GreEudcUnloadLinkW
  2997. (
  2998. const WCHAR * lpBaseFaceName,
  2999. COUNT cwcBaseFaceName,
  3000. const WCHAR * lpEudcFontPath,
  3001. COUNT cwcEudcFontPath
  3002. )
  3003. {
  3004. BOOL bRet = TRUE;
  3005. FLINKMESSAGE(DEBUG_FONTLINK_UNLOAD, "GreEudcUnloadLinkW()....\n");
  3006. GreAcquireSemaphore( ghsemEUDC1 );
  3007. //
  3008. // if text related API's using EUDC characters are in progess we must
  3009. // wait
  3010. //
  3011. ASSERTGDI(gcEUDCCount >= 0, "gcEUDCCount < 0");
  3012. if (gcEUDCCount > 0)
  3013. {
  3014. #if DBG
  3015. if( gflEUDCDebug & DEBUG_FONTLINK_LOAD )
  3016. {
  3017. DbgPrint("GreEudcLoadLinkW is waiting.\n");
  3018. }
  3019. #endif
  3020. // When the last text related API using EUDC characters finishes it will
  3021. // release us.
  3022. EngSetLastError(ERROR_LOCK_FAILED);
  3023. GreReleaseSemaphore( ghsemEUDC1 );
  3024. return (FALSE);
  3025. }
  3026. //
  3027. // Is this a request to load system wide eudc ?
  3028. //
  3029. if( lpBaseFaceName == NULL )
  3030. {
  3031. //
  3032. // if we have system wide eudc font, deactivate and unload it..
  3033. //
  3034. if( IS_SYSTEM_EUDC_PRESENT() )
  3035. {
  3036. //
  3037. // disable the link of all facename and system wide eudc.
  3038. //
  3039. vUnlinkAllEudcRFONTsAndPFEs(TRUE,FALSE);
  3040. //
  3041. // Unload system wide eudc font
  3042. //
  3043. bUnloadEudcFont( gappfeSysEUDC );
  3044. //
  3045. // set new system wide eudc data to global variable.
  3046. //
  3047. gappfeSysEUDC[PFE_NORMAL] = NULL;
  3048. gappfeSysEUDC[PFE_VERTICAL] = NULL;
  3049. gawcEUDCPath[0] = 0;
  3050. //
  3051. // Update global eudc timestamp.
  3052. //
  3053. ulSystemEUDCTimeStamp++;
  3054. if( !bWriteUserSystemEUDCRegistry(L"\0",1) )
  3055. {
  3056. WARNING("Unable to write new link to registry.\n");
  3057. }
  3058. }
  3059. }
  3060. else
  3061. {
  3062. ASSERTGDI(lpBaseFaceName != NULL,"GreEudcLoadLinkW():lpBaseFaceName == NULL\n");
  3063. ASSERTGDI(cwcBaseFaceName != 0,"GreEudcLoadLinkW():cwcBaseFaceName == 0\n");
  3064. ASSERTGDI(lpEudcFontPath != NULL,"GreEudcLoadLinkW():lpEudcFontPath == NULL\n");
  3065. ASSERTGDI(cwcEudcFontPath != 0,"GreEudcLoadLinkW():cwcEudcFontPath == 0\n");
  3066. //
  3067. // this is a request for facename link Eudc.
  3068. //
  3069. bRet = bDeleteFlEntry(lpBaseFaceName,lpEudcFontPath,FONTLINK_USER);
  3070. //
  3071. // if above call is failed, try FONTLINK_SYSTEM....
  3072. //
  3073. if( !bRet )
  3074. bRet = bDeleteFlEntry(lpBaseFaceName,lpEudcFontPath,FONTLINK_SYSTEM);
  3075. }
  3076. //
  3077. // Let others use EUDC characters again
  3078. //
  3079. GreReleaseSemaphore( ghsemEUDC1 );
  3080. return(bRet);
  3081. }
  3082. /*****************************************************************************
  3083. * ULONG NtGdiGetEudcTimeStampEx
  3084. *
  3085. * Shared kernel mode entry point for GetEudcTimeStamp and GetEudcTimeStampEx
  3086. *
  3087. * History
  3088. * 3-28-96 Gerrit van Wingerden [gerritv]
  3089. * Wrote it.
  3090. ****************************************************************************/
  3091. extern "C" ULONG NtGdiGetEudcTimeStampEx
  3092. (
  3093. LPWSTR lpBaseFaceName,
  3094. ULONG cwcBaseFaceName,
  3095. BOOL bSystemTimeStamp
  3096. )
  3097. {
  3098. WCHAR awcBaseFaceName[LF_FACESIZE+1];
  3099. ULONG ulRet = 0;
  3100. if(bSystemTimeStamp)
  3101. {
  3102. return(ulSystemEUDCTimeStamp);
  3103. }
  3104. else
  3105. if((lpBaseFaceName == NULL) || (cwcBaseFaceName == 0))
  3106. {
  3107. return(ulFaceNameEUDCTimeStamp);
  3108. }
  3109. if(cwcBaseFaceName <= LF_FACESIZE)
  3110. {
  3111. __try
  3112. {
  3113. ProbeForRead(lpBaseFaceName,cwcBaseFaceName*sizeof(WCHAR),sizeof(WCHAR));
  3114. RtlCopyMemory(awcBaseFaceName,lpBaseFaceName,
  3115. cwcBaseFaceName * sizeof(WCHAR));
  3116. awcBaseFaceName[cwcBaseFaceName] = L'\0';
  3117. ulRet = 0;
  3118. }
  3119. __except(EXCEPTION_EXECUTE_HANDLER)
  3120. {
  3121. WARNINGX(3100);
  3122. }
  3123. if(ulRet)
  3124. {
  3125. GreAcquireSemaphore( ghsemEUDC1 );
  3126. PFLENTRY pFlEntry;
  3127. if( (pFlEntry = FindBaseFontEntry(awcBaseFaceName)) != NULL )
  3128. {
  3129. ulRet = pFlEntry->ulTimeStamp;
  3130. }
  3131. else
  3132. {
  3133. ulRet = 0;
  3134. }
  3135. GreReleaseSemaphore( ghsemEUDC1 );
  3136. }
  3137. }
  3138. else
  3139. {
  3140. WARNING("NtGdiGetEudcTimeStampEx: Facename too big\n");
  3141. EngSetLastError(ERROR_INVALID_PARAMETER);
  3142. }
  3143. return(ulRet);
  3144. }
  3145. /******************************************************************************
  3146. * VOID vDrawGlyph( BYTE, UINT, GLYPHPOS )
  3147. *
  3148. * This routine draws a single glyph to a monochrome bitmap. It was stolen
  3149. * from textblt.cxx and modified to be faster since clipping doesn't come in
  3150. * to play in GetStringBitmapW.
  3151. *
  3152. * History:
  3153. * 5-18-93 Gerrit van Wingerden [gerritv]
  3154. * Wrote it.
  3155. *****************************************************************************/
  3156. static const BYTE ajMask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
  3157. static
  3158. VOID vDrawGlyph(
  3159. BYTE *pjBits, // pointer to base of bitmap bits
  3160. UINT cjScan, // size of a scan line
  3161. GLYPHPOS *pgp // glyph bits and location.
  3162. )
  3163. {
  3164. GLYPHBITS *pgb = pgp->pgdf->pgb;
  3165. ULONG cx = (ULONG) pgb->sizlBitmap.cx;
  3166. ULONG cy = (ULONG) pgb->sizlBitmap.cy;
  3167. if (cx == 0 || cy == 0)
  3168. return;
  3169. ULONG cjScanSrc = (cx + 7) >> 3;
  3170. PBYTE pjSrcHolder = pgb->aj;
  3171. ULONG xDst = pgp->ptl.x;
  3172. ULONG yDst = pgp->ptl.y;
  3173. PBYTE pjDstHolder = pjBits;
  3174. pjDstHolder += (yDst * cjScan );
  3175. pjDstHolder += (xDst >> 3);
  3176. // Set the source bits into the mono dib.
  3177. // We can make use of the fact that either xSrcDib or xDstDib is 0.
  3178. PBYTE pjDst;
  3179. PBYTE pjSrc;
  3180. if( !(xDst & 0x7) )
  3181. {
  3182. // Handle the simple case where xDib is byte-alligned
  3183. do
  3184. {
  3185. ULONG cBytes = cx >> 3;
  3186. pjSrc = pjSrcHolder;
  3187. pjDst = pjDstHolder;
  3188. pjSrcHolder += cjScanSrc;
  3189. pjDstHolder += cjScan;
  3190. while (cBytes--)
  3191. *pjDst++ |= *pjSrc++;
  3192. // Do the last partial byte.
  3193. if (cx & 0x7)
  3194. *pjDst |= *pjSrc & ajMask[cx & 0x7];
  3195. } while (--cy);
  3196. }
  3197. else // if (xDstDib)
  3198. {
  3199. // Handle the case where xDstDib is not byte-aligned.
  3200. int cShift = (int) xDst & 0x7;
  3201. do
  3202. {
  3203. ULONG cBytes = ((xDst + cx) >> 3) - (xDst >> 3);
  3204. pjSrc = pjSrcHolder;
  3205. pjDst = pjDstHolder;
  3206. pjSrcHolder += cjScanSrc;
  3207. pjDstHolder += cjScan;
  3208. WORD wSrc = (WORD) (*pjSrc++);
  3209. while (cBytes--)
  3210. {
  3211. *pjDst++ |= (BYTE) (wSrc >> cShift);
  3212. // don't read beyond src limit!
  3213. if (pjSrc == pjSrcHolder)
  3214. wSrc = (wSrc << 8);
  3215. else
  3216. wSrc = (wSrc << 8) | (WORD) (*pjSrc++);
  3217. }
  3218. // Do the last partial byte.
  3219. if ((xDst + cx) & 0x7)
  3220. *pjDst |= (BYTE) (wSrc >> cShift) & ajMask[(xDst+cx) & 0x7];
  3221. } while (--cy);
  3222. }
  3223. }
  3224. /******************************************************************************
  3225. * VOID vStringBitmapTextOut( STROBJ, BYTE, UINT )
  3226. *
  3227. * This routine draws a STROBJ to a monochrome bitmap. It is essentially
  3228. * EngTextOut but much faster since it doesn't have to wory about opaqueing,
  3229. * clipping, simulated rects, etc.
  3230. *
  3231. * History:
  3232. * 9-19-95 Hideyuki Nagase [hideyukn]
  3233. * Rewrote it.
  3234. *
  3235. * 5-18-93 Gerrit van Wingerden [gerritv]
  3236. * Wrote it.
  3237. *****************************************************************************/
  3238. static
  3239. VOID vStringBitmapTextOut(
  3240. STROBJ *pstro, // Pointer to STROBJ.
  3241. BYTE *pjBits, // Pointer to buffer to store glyph image.
  3242. UINT cjScan // Size of buffer.
  3243. )
  3244. {
  3245. BOOL bMoreGlyphs;
  3246. GLYPHPOS *pgp = (GLYPHPOS*)NULL;
  3247. LONG xAdjust = ( pstro->rclBkGround.left > 0 ) ? 0 : pstro->rclBkGround.left;
  3248. LONG yAdjust = pstro->rclBkGround.top;
  3249. ((ESTROBJ*)pstro)->vEnumStart();
  3250. if( pstro->pgp == (GLYPHPOS *) NULL )
  3251. {
  3252. ULONG cGlyph;
  3253. bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp);
  3254. }
  3255. else
  3256. {
  3257. pgp = pstro->pgp;
  3258. bMoreGlyphs = FALSE;
  3259. }
  3260. ASSERTGDI(bMoreGlyphs == FALSE,"vStringBitmapTextOut() bMoreGlyphs is TRUE.\n");
  3261. // Saw this on FE stress
  3262. // ASSERTGDI(pgp, "vStringBitmapTextOut() STROBJ_bEnum returns NULL pgp.\n");
  3263. // fail textout if pgp == NULL
  3264. if (pgp)
  3265. {
  3266. GLYPHBITS *pgb = pgp[0].pgdf->pgb;
  3267. pgp[0].ptl.x += pgb->ptlOrigin.x - xAdjust;
  3268. pgp[0].ptl.y += pgb->ptlOrigin.y - yAdjust;
  3269. //
  3270. // Blt the glyph into the bitmap
  3271. //
  3272. vDrawGlyph( pjBits, cjScan, &pgp[0] );
  3273. }
  3274. }
  3275. /******************************************************************************
  3276. * UINT GreGetStringBitmapW
  3277. *
  3278. * This routine does a kindof fast text out ( with restrictions ) to a monochrome
  3279. * bitmap.
  3280. *
  3281. * History:
  3282. * 9-19-95 Hideyuki Nagase [hideyukn]
  3283. * Rewrote it.
  3284. *
  3285. * 5-18-93 Gerrit van Wingerden [gerritv]
  3286. * Wrote it.
  3287. *****************************************************************************/
  3288. UINT GreGetStringBitmapW(
  3289. HDC hdc,
  3290. LPWSTR pwsz,
  3291. UINT cwc, // should be 1....
  3292. LPSTRINGBITMAP lpSB,
  3293. UINT cj,
  3294. UINT *puiOffset // not used...
  3295. )
  3296. {
  3297. // Parameter check, early out...
  3298. if( cwc != 1 )
  3299. {
  3300. WARNING("GreGetStringBitmap only works when char count is 1.\n");
  3301. return(0);
  3302. }
  3303. if( puiOffset != 0 && *puiOffset != 0 )
  3304. {
  3305. WARNING("GreGetStringBitmap only works when offset is 0.\n");
  3306. return(0);
  3307. }
  3308. // Lock the DC and set the new attributes.
  3309. DCOBJ dco(hdc); // Lock the DC.
  3310. if (!dco.bValid()) // Check if it's good.
  3311. {
  3312. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  3313. return(0);
  3314. }
  3315. // Get the transform from the DC.
  3316. EXFORMOBJ xo(dco,WORLD_TO_DEVICE);
  3317. // we only allow identity transforms for GetStringBitmap
  3318. if( !xo.bIdentity() )
  3319. {
  3320. WARNING("GreGetStringBitmap only works with identity WtoD xforms.\n");
  3321. return(0);
  3322. }
  3323. // Locate the font cache.
  3324. RFONTOBJ rfo(dco,FALSE);
  3325. if (!rfo.bValid())
  3326. {
  3327. WARNING("gdisrv!GreGetStringBitmap(): could not lock RFONTOBJ\n");
  3328. return (0);
  3329. }
  3330. // GetStringBitmap doesn't support vector fonts.
  3331. if( rfo.bPathFont() )
  3332. {
  3333. WARNING("gdisrv!GetStringBitmap() : vector fonts aren't supported.\n");
  3334. return(0);
  3335. }
  3336. // GetStringBitmap doesn't support sny rotations.
  3337. if((dco.pdc->lEscapement() | rfo.ulOrientation() ) != 0)
  3338. {
  3339. WARNING("gdisrv!GreGetStringBitmap(): Text isn't Horizontal.\n" );
  3340. return(0);
  3341. }
  3342. // Initialize ESTROBJ. Compute glyph layout positions.
  3343. ESTROBJ to; to.vInitSimple(pwsz,cwc,dco,rfo,0L,0L,NULL);
  3344. if (!to.bValid())
  3345. {
  3346. WARNING("gdisrv!GetStringBitmap() : could not lock ESTROBJ.\n");
  3347. return(0);
  3348. }
  3349. // Compute the target string rectangle.
  3350. UINT uiWidth = (UINT)( to.rclBkGround.right - to.rclBkGround.left );
  3351. UINT uiHeight = (UINT)( to.rclBkGround.bottom - to.rclBkGround.top );
  3352. // Offset the width by the C space of the last character and the A space of
  3353. // the first character to get the true extent
  3354. GLYPHDATA *pgd;
  3355. EGLYPHPOS *pg = (EGLYPHPOS*)to.pgpGet();
  3356. pgd = pg->pgd();
  3357. uiWidth += FXTOL(pgd->fxA);
  3358. pg = &pg[to.cGlyphsGet()-1];
  3359. pgd = pg->pgd();
  3360. uiWidth += FXTOL((pgd->fxD-pgd->fxAB));
  3361. // compute width of scanline in bytes ( must be byte alligned )
  3362. UINT cjScan = (uiWidth + 7) / 8;
  3363. UINT cjSize = offsetof(STRINGBITMAP,ajBits) + (cjScan * uiHeight);
  3364. PBYTE pjBits = lpSB->ajBits;
  3365. // If the user only want the size return now.
  3366. // And check the buffer is enough to store glyph image
  3367. if( cj < cjSize ) return( cjSize );
  3368. // Clear the target buffer.
  3369. RtlZeroMemory( pjBits, cjScan * uiHeight );
  3370. // Fill up its bitmap size...
  3371. lpSB->uiHeight = uiHeight;
  3372. lpSB->uiWidth = uiWidth;
  3373. // adjust the baseline of the Sys EUDC for win 3.1 compatability
  3374. POINTL ptlBaseLineAdjust = {0,0};
  3375. LONG lFontType = EUDCTYPE_BASEFONT;
  3376. PRFONT pLinkedRfont = NULL;
  3377. // Is the character linked one ?
  3378. if( to.bLinkedGlyphs() )
  3379. {
  3380. // Setup its font type...
  3381. lFontType = *(LONG *)(to.plPartitionGet());
  3382. // Get corresponding RFONT with current linked font.
  3383. switch (lFontType)
  3384. {
  3385. case EUDCTYPE_SYSTEM_WIDE:
  3386. pLinkedRfont = rfo.prfntSysEUDC();
  3387. break;
  3388. case EUDCTYPE_SYSTEM_TT_FONT:
  3389. pLinkedRfont = rfo.prfntSystemTT();
  3390. break;
  3391. case EUDCTYPE_DEFAULT:
  3392. pLinkedRfont = rfo.prfntDefEUDC();
  3393. break;
  3394. case EUDCTYPE_BASEFONT:
  3395. // it's possible for this to be the case since the EUDC character
  3396. // could have been a singular character or a blank character in which
  3397. // case we will have already have set flags saying we have linked
  3398. // glyphs but in actuality will grab the default glyph from the base font
  3399. break;
  3400. default:
  3401. ASSERTGDI(lFontType >= EUDCTYPE_FACENAME,
  3402. "GDISRV:GreGetStringBitmapW() Error lFontType\n");
  3403. pLinkedRfont = rfo.prfntFaceName(lFontType - EUDCTYPE_FACENAME);
  3404. break;
  3405. }
  3406. // Is the RFONT is valid ?
  3407. if( pLinkedRfont != NULL )
  3408. {
  3409. RFONTTMPOBJ rfoLink(pLinkedRfont);
  3410. //
  3411. // Compute baseline diffs.
  3412. //
  3413. // *** Base font Height == Linked font Height ***
  3414. //
  3415. // Base font EUDC font Base font EUDC font
  3416. //
  3417. // -------
  3418. // ------- | | ------- -------
  3419. // | | | | -----> | | | |
  3420. // | 15 | | 20 | | 15 | | 15 |
  3421. // | | | | | | | |
  3422. // -------------------- BaseLine ---------------------
  3423. // | 5 | | 5 | | 5 |
  3424. // ------- ------- -------
  3425. //
  3426. // *** Base font Ascent >= Linked font Height ****
  3427. //
  3428. // Base font EUDC font Base font EUDC font
  3429. //
  3430. // ------- -------
  3431. // | | | | -------
  3432. // | | ------- -----> | | | |
  3433. // | 20 | | 10 | | 20 | | 15 |
  3434. // | | | | | | | |
  3435. // -------------------- BaseLine ---------------------
  3436. // | 5 | | 5 | | 5 |
  3437. // ------- ------- -------
  3438. //
  3439. // *** Others ****
  3440. //
  3441. // TBD.
  3442. //
  3443. if( rfo.fxMaxAscent() >= (rfoLink.fxMaxAscent() - rfoLink.fxMaxDescent()) )
  3444. {
  3445. ptlBaseLineAdjust.y = (rfoLink.fxMaxDescent() >> 4);
  3446. }
  3447. else
  3448. {
  3449. ptlBaseLineAdjust.y = (rfoLink.fxMaxAscent() - rfo.fxMaxAscent()) >> 4;
  3450. }
  3451. //
  3452. // if we need to adjust baseline, force emulation....
  3453. //
  3454. if( ptlBaseLineAdjust.y ) to.pgpSet(NULL);
  3455. }
  3456. }
  3457. // Set current font type.
  3458. to.vFontSet(lFontType);
  3459. RFONTTMPOBJ rfoLink(pLinkedRfont);
  3460. if(pLinkedRfont)
  3461. {
  3462. to.prfntSet( &rfoLink );
  3463. }
  3464. // Set base line adjustment delta.
  3465. to.ptlBaseLineAdjustSet( ptlBaseLineAdjust );
  3466. // Draw the glyph
  3467. vStringBitmapTextOut( (STROBJ*)&to, pjBits, cjScan );
  3468. return( cj );
  3469. }
  3470. BOOL bAdjusBaseLine(RFONTOBJ &rfoBase, RFONTOBJ &rfoLink, POINTL *pptlAdjustBaseLine)
  3471. {
  3472. BOOL bRet = FALSE;
  3473. // special case of the bitmap font, the heights are the same
  3474. if ((rfoBase.fxMaxAscent() - rfoBase.fxMaxDescent()) ==
  3475. (rfoLink.fxMaxAscent() - rfoLink.fxMaxDescent()))
  3476. {
  3477. pptlAdjustBaseLine->x = FXTOLFLOOR((rfoBase.ptfxMaxAscent().x - rfoLink.ptfxMaxAscent().x));
  3478. pptlAdjustBaseLine->y = FXTOLFLOOR((rfoBase.ptfxMaxAscent().y - rfoLink.ptfxMaxAscent().y));
  3479. if (pptlAdjustBaseLine->y || pptlAdjustBaseLine->x)
  3480. bRet = TRUE;
  3481. }
  3482. return bRet;
  3483. }
  3484. /*******************************************************************************
  3485. * void AdjustBoundingBox(RFONTOBJ&, RFONTOBJ&, POINTFIX*, ERECTL*)
  3486. *
  3487. * This function adjusts the baseline of the EUDC font in a way that is
  3488. * Win 3.1 compatible according to the following rules:
  3489. *
  3490. *
  3491. * Base font Height == Linked font Height ***
  3492. *
  3493. * Base font EUDC font Base font EUDC font
  3494. *
  3495. ******************************************************************************/
  3496. static
  3497. void AdjustBoundingBox(
  3498. RFONTOBJ &rfoBase,
  3499. RFONTOBJ &rfoLink,
  3500. FIX *fxAdjustDeltaAsc,
  3501. FIX *fxAdjustDeltaDsc,
  3502. POINTFIX *ptfxDeltaAsc,
  3503. POINTFIX *ptfxDeltaDsc
  3504. )
  3505. {
  3506. FIX fxDeltaDsc, fxDeltaAsc;
  3507. fxDeltaDsc = rfoBase.fxMaxDescent() - rfoLink.fxMaxDescent();
  3508. fxDeltaAsc = -(rfoBase.fxMaxAscent() - rfoLink.fxMaxAscent());
  3509. // There is no internal leading in base font, most likely BMP case.
  3510. // In this case we will adjust the baseline (the exact height match)
  3511. // so that it will not be necessary to adjust the bounding box
  3512. if ((fxDeltaDsc + fxDeltaAsc) == 0)
  3513. return;
  3514. if (fxDeltaDsc < 0)
  3515. fxDeltaDsc = 0;
  3516. if(fxDeltaAsc < 0)
  3517. fxDeltaAsc = 0;
  3518. if(!fxDeltaAsc && !fxDeltaDsc )
  3519. return;
  3520. // eAu = (0, -1)
  3521. // dA = eA * eAu = (x1, y1)
  3522. // dD = -eD * eDu = (x2, y2)
  3523. if (fxDeltaDsc > *fxAdjustDeltaDsc)
  3524. {
  3525. *fxAdjustDeltaDsc = fxDeltaDsc;
  3526. ptfxDeltaDsc->x = -(rfoBase.ptfxMaxDescent().x - rfoLink.ptfxMaxDescent().x);
  3527. ptfxDeltaDsc->y = -(rfoBase.ptfxMaxDescent().y - rfoLink.ptfxMaxDescent().y);
  3528. }
  3529. if (fxDeltaAsc > *fxAdjustDeltaAsc)
  3530. {
  3531. *fxAdjustDeltaAsc = fxDeltaAsc;
  3532. ptfxDeltaAsc->x = -(rfoBase.ptfxMaxAscent().x - rfoLink.ptfxMaxAscent().x);
  3533. ptfxDeltaAsc->y = -(rfoBase.ptfxMaxAscent().y - rfoLink.ptfxMaxAscent().y);
  3534. }
  3535. }
  3536. VOID ESTROBJ::vEudcOpaqueArea(POINTFIX *aptfxBackground, BOOL bComplexBackground )
  3537. {
  3538. FIX fxDeltaAsc = 0;
  3539. FIX fxDeltaDsc = 0;
  3540. POINTFIX ptfxDeltaAsc = {0, 0};
  3541. POINTFIX ptfxDeltaDsc = {0, 0};
  3542. for(LONG lFont = EUDCTYPE_BASEFONT ;
  3543. lFont < (EUDCTYPE_FACENAME + (LONG) prfo->uiNumFaceNameLinks()) ;
  3544. lFont++ )
  3545. {
  3546. RFONTTMPOBJ rfoLink;
  3547. switch( lFont )
  3548. {
  3549. case EUDCTYPE_BASEFONT:
  3550. break;
  3551. case EUDCTYPE_SYSTEM_TT_FONT:
  3552. if(cTTSysGlyphs)
  3553. {
  3554. rfoLink.vInit(prfo->prfntSystemTT());
  3555. AdjustBoundingBox(*prfo,rfoLink, &fxDeltaAsc, &fxDeltaDsc,
  3556. &ptfxDeltaAsc, &ptfxDeltaDsc);
  3557. }
  3558. break;
  3559. case EUDCTYPE_SYSTEM_WIDE:
  3560. if( cSysGlyphs )
  3561. {
  3562. rfoLink.vInit( prfo->prfntSysEUDC() );
  3563. AdjustBoundingBox(*prfo,rfoLink, &fxDeltaAsc, &fxDeltaDsc,
  3564. &ptfxDeltaAsc, &ptfxDeltaDsc);
  3565. }
  3566. break;
  3567. case EUDCTYPE_DEFAULT:
  3568. if( cDefGlyphs)
  3569. {
  3570. rfoLink.vInit( prfo->prfntDefEUDC() );
  3571. AdjustBoundingBox(*prfo,rfoLink, &fxDeltaAsc, &fxDeltaDsc,
  3572. &ptfxDeltaAsc, &ptfxDeltaDsc);
  3573. }
  3574. break;
  3575. default:
  3576. if( pacFaceNameGlyphs && pacFaceNameGlyphs[lFont-EUDCTYPE_FACENAME])
  3577. {
  3578. rfoLink.vInit(prfo->prfntFaceName(lFont - EUDCTYPE_FACENAME));
  3579. AdjustBoundingBox(*prfo,rfoLink, &fxDeltaAsc, &fxDeltaDsc,
  3580. &ptfxDeltaAsc, &ptfxDeltaDsc);
  3581. }
  3582. break;
  3583. }
  3584. }
  3585. if (fxDeltaAsc || fxDeltaDsc)
  3586. {
  3587. LONG lDeltaL, lDeltaR, lDeltaT, lDeltaB;
  3588. RECTL rclInflate = rclBkGround;
  3589. // dLeft = min(x1, x2)
  3590. // dRight = max(x1, x2)
  3591. // dTop = min(y1, y2)
  3592. // dBottom = max(y1, y2)
  3593. lDeltaL = FXTOLFLOOR(min(ptfxDeltaAsc.x, ptfxDeltaDsc.x));
  3594. lDeltaR = FXTOLCEILING(max(ptfxDeltaAsc.x, ptfxDeltaDsc.x));
  3595. lDeltaT = FXTOLFLOOR(min(ptfxDeltaAsc.y, ptfxDeltaDsc.y));
  3596. lDeltaB = FXTOLCEILING(max(ptfxDeltaAsc.y, ptfxDeltaDsc.y));
  3597. rclInflate.left += lDeltaL;
  3598. rclInflate.right += lDeltaR;
  3599. rclInflate.top += lDeltaT;
  3600. rclInflate.bottom += lDeltaB;
  3601. if (rclInflate.top < rclBkGround.top)
  3602. rclBkGround.top = rclInflate.top;
  3603. if (rclInflate.bottom > rclBkGround.bottom)
  3604. rclBkGround.bottom = rclInflate.bottom;
  3605. if (rclInflate.left < rclBkGround.left)
  3606. rclBkGround.left = rclInflate.left;
  3607. if (rclInflate.right > rclBkGround.right)
  3608. rclBkGround.right = rclInflate.right;
  3609. // for the order of points in the bounding paralelogram look at textobj.cxx
  3610. // we go around clockwise ie tl, tr, br, bl
  3611. if (bComplexBackground)
  3612. {
  3613. if (fxDeltaAsc)
  3614. {
  3615. aptfxBackground[0].x += ptfxDeltaAsc.x;
  3616. aptfxBackground[0].y += ptfxDeltaAsc.y;
  3617. aptfxBackground[1].x += ptfxDeltaAsc.x;
  3618. aptfxBackground[1].y += ptfxDeltaAsc.y;
  3619. }
  3620. if (fxDeltaDsc)
  3621. {
  3622. aptfxBackground[2].x += ptfxDeltaDsc.x;
  3623. aptfxBackground[2].y += ptfxDeltaDsc.y;
  3624. aptfxBackground[3].x += ptfxDeltaDsc.x;
  3625. aptfxBackground[3].y += ptfxDeltaDsc.y;
  3626. }
  3627. }
  3628. }
  3629. }
  3630. static
  3631. BOOL bOutOfBounds(STROBJ *pstro, RFONTOBJ *prfo)
  3632. {
  3633. COUNT cGlyph;
  3634. BOOL bMoreGlyphs;
  3635. GLYPHPOS *pgp;
  3636. BOOL bRet = FALSE;
  3637. if((*((LONG*) &(prfo->pfdx()->eXY)) == 0 && *((LONG*)&(prfo->pfdx()->eYX)) == 0))
  3638. {
  3639. // fast out for horizontal cases
  3640. return(FALSE);
  3641. }
  3642. do
  3643. {
  3644. bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp);
  3645. if(cGlyph)
  3646. {
  3647. LONG xL, xR, yT, yB;
  3648. ULONG ii;
  3649. for (ii=0; ii<cGlyph; ii++)
  3650. {
  3651. // for device font pgb will be NULL so don't do the check
  3652. if(pgp[ii].pgdf->pgb)
  3653. {
  3654. xL = pgp[ii].ptl.x + pgp[ii].pgdf->pgb->ptlOrigin.x;
  3655. xR = xL + pgp[ii].pgdf->pgb->sizlBitmap.cx;
  3656. yT = pgp[ii].ptl.y + pgp[ii].pgdf->pgb->ptlOrigin.y;
  3657. yB = yT + pgp[ii].pgdf->pgb->sizlBitmap.cy;
  3658. if( (xL < pstro->rclBkGround.left) ||
  3659. (xR > pstro->rclBkGround.right) ||
  3660. (yT < pstro->rclBkGround.top) ||
  3661. (yB > pstro->rclBkGround.bottom) )
  3662. {
  3663. bRet = TRUE;
  3664. break;
  3665. }
  3666. }
  3667. }
  3668. }
  3669. } while(bMoreGlyphs);
  3670. // reset it for the text out call
  3671. STROBJ_vEnumStart(pstro);
  3672. return(bRet);
  3673. }
  3674. /******************************************************************************
  3675. * BOOL bProxyDrvTextOut()
  3676. *
  3677. * This routine takes the place of a DrvTextOut in the case when there are EUDC
  3678. * characters in the ESTROBJ. It partitions the call into mutliple DrvTextOut
  3679. * calls, one for each font int the string.
  3680. *
  3681. * Partitioning information is stored in an array of LONGS in the RFONTOBJ.
  3682. * The i'th entry in the array tells what font the i'th glyph in the ESTROBJ
  3683. * belongs to.
  3684. *
  3685. * History:
  3686. * 7-14-93 Gerrit van Wingerden [gerritv]
  3687. * Rewrote it to handle multiple face name links and just be better.
  3688. * 2-10-93 Gerrit van Wingerden [gerritv]
  3689. * Wrote it.
  3690. *
  3691. *****************************************************************************/
  3692. // This routine is used to partition calls to the driver if there are EUDC
  3693. // characters in the string.
  3694. BOOL bProxyDrvTextOut
  3695. (
  3696. XDCOBJ& dco,
  3697. SURFACE *pSurf,
  3698. ESTROBJ& to,
  3699. ECLIPOBJ& co,
  3700. RECTL *prclExtra,
  3701. RECTL *prclBackground,
  3702. BRUSHOBJ *pboFore,
  3703. BRUSHOBJ *pboOpaque,
  3704. POINTL *pptlBrushOrg,
  3705. RFONTOBJ& rfo,
  3706. PDEVOBJ *pdo,
  3707. FLONG flCaps,
  3708. RECTL *prclExclude
  3709. )
  3710. {
  3711. RFONTOBJ *prfoSave;
  3712. LONG *plPartition, *plPartitionEnd;
  3713. COUNT cTotalGlyphs = 0;
  3714. LONG lInflatedMax = 0;
  3715. WCHAR *pwcPartition, *pwcTmp, *pwcSave, *pwcSource;
  3716. ULONG cNumGlyphs = to.cGlyphsGet();
  3717. POINTL ptlAdjustBaseLine;
  3718. BOOL bSkip = FALSE;
  3719. prfoSave = to.prfo;
  3720. BOOL bRet = TRUE;
  3721. pwcPartition = to.pwcPartitionGet();
  3722. // now partition the EUDC glyphs by font
  3723. pwcSave = to.pwszGet();
  3724. // set to NULL to force enumeration
  3725. to.pgpSet( NULL );
  3726. // This code is only for NT bug #414953
  3727. // If the base font is stroke base then we would not allow to render the linked TT font
  3728. if ((rfo.prfnt->flInfo & FM_INFO_TECH_STROKE) &&
  3729. rfo.iGraphicsMode() == GM_COMPATIBLE)
  3730. {
  3731. if ((dco.pdc->lEscapement() != (LONG) rfo.prfnt->ulOrientation))
  3732. bSkip = TRUE;
  3733. }
  3734. // Turn off acclerators since we'll seriously munge the properties of the string object.
  3735. // also clear the ulCharInc value since the tga driver won't work properly if it's
  3736. // set
  3737. to.flAccelSet( 0 );
  3738. to.vClearCharInc();
  3739. for(LONG lFont = EUDCTYPE_BASEFONT ;
  3740. lFont < (EUDCTYPE_FACENAME + (LONG) rfo.uiNumFaceNameLinks()) ;
  3741. lFont++ )
  3742. {
  3743. RFONTTMPOBJ rfoLink;
  3744. RFONTOBJ *prfoLink;
  3745. UINT ii;
  3746. COUNT cLinkedGlyphs;
  3747. switch( lFont )
  3748. {
  3749. case EUDCTYPE_BASEFONT:
  3750. // If there aren't any glyphs in the base font just draw the
  3751. // opaque rectangle. We must draw the opaque rectangle here
  3752. // because the linked glyphs don't neccesarily fit into the
  3753. // the opaque rectangle. Passing such a rectangle to a driver
  3754. // can cause unexpected results.
  3755. cLinkedGlyphs = to.cSysGlyphsGet() + to.cDefGlyphsGet() +
  3756. to.cTTSysGlyphsGet();
  3757. for( ii = 0; ii < rfo.uiNumFaceNameLinks(); ii++ )
  3758. {
  3759. cLinkedGlyphs += to.cFaceNameGlyphsGet( ii );
  3760. }
  3761. if( cLinkedGlyphs == cNumGlyphs )
  3762. {
  3763. // Draw the opaque rectangle here if there is one
  3764. ASSERTGDI(prclExclude, "bProxyDrvTextOut: prclExclude is NULL\n");
  3765. if(prclBackground != NULL)
  3766. {
  3767. co.erclExclude().left =
  3768. max(prclExclude->left,prclBackground->left);
  3769. co.erclExclude().right =
  3770. min(prclExclude->right,prclBackground->right);
  3771. co.erclExclude().top =
  3772. max(prclExclude->top,prclBackground->top);
  3773. co.erclExclude().bottom =
  3774. min(prclExclude->bottom,prclBackground->bottom);
  3775. }
  3776. // if not clipped, Just paint the rectangle.
  3777. if ((co.erclExclude().left < co.erclExclude().right) &&
  3778. (co.erclExclude().top < co.erclExclude().bottom) &&
  3779. prclBackground != NULL )
  3780. {
  3781. INC_SURF_UNIQ(pSurf);
  3782. TextOutBitBlt
  3783. (
  3784. pSurf,
  3785. rfo,
  3786. (SURFOBJ *) NULL, // Source surface.
  3787. (SURFOBJ *) NULL, // Mask surface.
  3788. &co, // Clip object.
  3789. (XLATEOBJ *) NULL, // Palette translation object.
  3790. prclBackground, // Destination rectangle.
  3791. (POINTL *) NULL, // Source origin.
  3792. (POINTL *) NULL, // Mask origin.
  3793. (BRUSHOBJ *) pboOpaque, // Realized opaque brush.
  3794. pptlBrushOrg, // brush origin
  3795. 0x0000f0f0 // PATCOPY
  3796. );
  3797. }
  3798. co.erclExclude() = *prclExclude;
  3799. // set prclBackground to NULL since we have just drawn it
  3800. prclBackground = NULL;
  3801. continue;
  3802. }
  3803. prfoLink = &rfo;
  3804. FLINKMESSAGE(DEBUG_FONTLINK_TEXTOUT,"Doing base font.\n");
  3805. break;
  3806. case EUDCTYPE_SYSTEM_TT_FONT:
  3807. if(bSkip || (to.cTTSysGlyphsGet() == 0))
  3808. {
  3809. continue;
  3810. }
  3811. rfoLink.vInit(rfo.prfntSystemTT());
  3812. prfoLink = (RFONTOBJ *) &rfoLink;
  3813. break;
  3814. case EUDCTYPE_SYSTEM_WIDE:
  3815. if(bSkip || (to.cSysGlyphsGet() == 0))
  3816. {
  3817. continue;
  3818. }
  3819. rfoLink.vInit( rfo.prfntSysEUDC() );
  3820. prfoLink = (RFONTOBJ *) &rfoLink;
  3821. break;
  3822. case EUDCTYPE_DEFAULT:
  3823. if(bSkip || (to.cDefGlyphsGet() == 0) )
  3824. {
  3825. continue;
  3826. }
  3827. rfoLink.vInit( rfo.prfntDefEUDC() );
  3828. prfoLink = (RFONTOBJ *) &rfoLink;
  3829. break;
  3830. default:
  3831. if( bSkip || (to.cFaceNameGlyphsGet( lFont-EUDCTYPE_FACENAME ) == 0) )
  3832. {
  3833. continue;
  3834. }
  3835. rfoLink.vInit(rfo.prfntFaceName(lFont - EUDCTYPE_FACENAME));
  3836. prfoLink = (RFONTOBJ *) &rfoLink;
  3837. break;
  3838. }
  3839. // Loop through all the glyphs in the TextObj using plPartition to
  3840. // and construct a wchar array to match this textobj.
  3841. for( plPartition = to.plPartitionGet(),plPartitionEnd = &plPartition[cNumGlyphs],
  3842. pwcSource = pwcSave, pwcTmp = pwcPartition;
  3843. plPartition < plPartitionEnd;
  3844. plPartition += 1, pwcSource += 1 )
  3845. {
  3846. if( *plPartition == lFont )
  3847. {
  3848. *pwcTmp++ = *pwcSource;
  3849. }
  3850. }
  3851. // Keep track of the total glyphs drawn so far so we know when we are doing
  3852. // the last DrvTextOut. On the last DrvTextOut draw prclExtra.
  3853. cTotalGlyphs += (COUNT) ( pwcTmp - pwcPartition );
  3854. to.cGlyphsSet( (LONG) ( pwcTmp - pwcPartition ));
  3855. to.pwszSet( pwcPartition );
  3856. // set the font type and reset cGlyphPosCopied to 0
  3857. to.vFontSet( lFont );
  3858. if (lFont != EUDCTYPE_BASEFONT)
  3859. {
  3860. if (bAdjusBaseLine(rfo, rfoLink, &ptlAdjustBaseLine))
  3861. {
  3862. to.ptlBaseLineAdjustSet(ptlAdjustBaseLine);
  3863. }
  3864. }
  3865. // adjust the baseline of the Sys EUDC for win 3.1 compatability
  3866. to.prfntSet( prfoLink );
  3867. // some drivers dink with the BkGround rectangle (like the Cirrus driver )
  3868. // so save a copy here and then restore it later to handle this situation
  3869. to.vSaveBkGroundRect();
  3870. // check this is a path draw or not.
  3871. if( prfoLink->bPathFont() )
  3872. {
  3873. PATHMEMOBJ po;
  3874. if( !po.bValid() )
  3875. {
  3876. SAVE_ERROR_CODE( ERROR_NOT_ENOUGH_MEMORY );
  3877. bRet = FALSE;
  3878. }
  3879. else
  3880. {
  3881. if( !(prfoLink->bReturnsOutlines()) )
  3882. {
  3883. //
  3884. // VECTOR FONT CASE
  3885. //
  3886. if( !to.bTextToPathWorkhorse(po) ||
  3887. !po.bSimpleStroke1( flCaps,
  3888. pdo,
  3889. pSurf,
  3890. &co,
  3891. pboFore,
  3892. pptlBrushOrg,
  3893. ( R2_COPYPEN | ( R2_COPYPEN << 8 ))
  3894. ))
  3895. {
  3896. #if DBG
  3897. DbgPrint("ProxyDrvTextout:bTextToPath for vector font \
  3898. failed(%d).\n", lFont);
  3899. #endif
  3900. bRet = FALSE;
  3901. }
  3902. }
  3903. else
  3904. {
  3905. //
  3906. // OUTLINE FONT CASE
  3907. //
  3908. if( !to.bTextToPathWorkhorse(po) ||
  3909. (( po.cCurves > 1 ) &&
  3910. !po.bSimpleFill( flCaps,
  3911. pdo,
  3912. pSurf,
  3913. &co,
  3914. pboFore,
  3915. pptlBrushOrg,
  3916. ( R2_COPYPEN | ( R2_COPYPEN << 8 )),
  3917. WINDING
  3918. )
  3919. )
  3920. )
  3921. {
  3922. #if DBG
  3923. DbgPrint("ProxyDrvTextout:bTextToPath for outline font \
  3924. failed(%d).\n",lFont);
  3925. #endif
  3926. bRet = FALSE;
  3927. }
  3928. }
  3929. }
  3930. }
  3931. else
  3932. {
  3933. // This is bad but we will peform a check to see if the linked glyphs
  3934. // are out of bounds and if so fail the call. There are several reasons
  3935. // why this may happen (some understood and some not yet understood). Since
  3936. // we are so close to shipping it was better to do this rather than make
  3937. // riskier fixes for the other problems. I should point out a few things:
  3938. //
  3939. // 1) We only do this check on rotations that are not multiples of 90.
  3940. // These cases don't cause problem. This also means we are only
  3941. // Slowing done non-common cases. bOutOfBounds returns TRUE
  3942. // right away for horizontal text.
  3943. // 2) It is always better to fail in this case since the alternative is
  3944. // is system crash (of course fixing the underlying problems is ideal.)
  3945. // 3) These cases are not real world (i.e. they won't affect text in
  3946. // in real world scenarios) since they occur under extremely bizarre
  3947. // transforms and only in our test apps.
  3948. // 4) I am documenting what I have found about the failure cases so far
  3949. // and fix these in 5.0
  3950. if(!bOutOfBounds((STROBJ*) &to, prfoLink))
  3951. {
  3952. PFN_DrvTextOut pfnTextOut;
  3953. pfnTextOut = pSurf->pfnTextOut();
  3954. // this code correspond to what is done in GreExtTextOutWLocked()
  3955. // see MSPaint, ClearType bug under 16bits colors #106984
  3956. // If the pointer to the TextOut function points to SpTextOut then
  3957. // we know that AntiAliased text can be handled and we can skip
  3958. // the funny business in the else clause
  3959. if (pfnTextOut == SpTextOut)
  3960. {
  3961. if (prfoLink->prfnt->fobj.flFontType & (FO_GRAY16 | FO_CLEARTYPE_X))
  3962. {
  3963. pSurf->pdcoAA = &dco;
  3964. }
  3965. }
  3966. else
  3967. {
  3968. if
  3969. (
  3970. (prfoLink->prfnt->fobj.flFontType & FO_GRAY16) &&
  3971. (!(dco.flGraphicsCaps() & GCAPS_GRAY16) ||
  3972. (prfoLink->prfnt->fobj.flFontType & FO_CLEARTYPE_X))
  3973. )
  3974. {
  3975. // Inform SpTextOut that this call came from GreExtTextOutW
  3976. // for the purpose of rendering anti aliased text on a device
  3977. // that does not support it. Remember to set this to zero
  3978. // before releasing the surface to other users.
  3979. if (pfnTextOut != EngTextOut)
  3980. pSurf->pdcoAA = &dco;
  3981. pfnTextOut = SpTextOut;
  3982. }
  3983. } // if (pfnTextOut == SpTextOut) else
  3984. prfoLink->PreTextOut(dco);
  3985. //
  3986. // WINBUG #214225: re-visit the issue that RFONT cache semaphore
  3987. // is held too long period of time.
  3988. // Release/acquire the base rfont semaphore before/after
  3989. // the DrvTextOut call.
  3990. //
  3991. {
  3992. PDEVOBJ po(pSurf->hdev());
  3993. BOOL bAcquireSem = FALSE;
  3994. if (prfoLink != (&rfo) && po.bPrinter() && po.bUMPD())
  3995. {
  3996. if (rfo.prfnt->hsemCache != NULL &&
  3997. GreIsSemaphoreOwnedByCurrentThread(rfo.prfnt->hsemCache))
  3998. {
  3999. GreReleaseSemaphore(rfo.prfnt->hsemCache);
  4000. bAcquireSem = TRUE;
  4001. }
  4002. }
  4003. if(!((*pfnTextOut))
  4004. ( pSurf->pSurfobj(),
  4005. (STROBJ *) &to,
  4006. prfoLink->pfo(),
  4007. &co,
  4008. (cTotalGlyphs == cNumGlyphs ) ? prclExtra : NULL,
  4009. prclBackground,
  4010. pboFore,
  4011. pboOpaque,
  4012. pptlBrushOrg,
  4013. (R2_COPYPEN | (R2_COPYPEN << 8))
  4014. ))
  4015. {
  4016. #if DBG
  4017. DbgPrint("ProxyDrvTextout:DrvTextOut for bitmap font failed(%d).\n",
  4018. lFont);
  4019. #endif
  4020. bRet = FALSE;
  4021. }
  4022. if (bAcquireSem)
  4023. {
  4024. GreAcquireSemaphore(rfo.prfnt->hsemCache);
  4025. }
  4026. }
  4027. prfoLink->PostTextOut(dco);
  4028. pSurf->pdcoAA = 0; // clear AA state
  4029. }
  4030. // set this to NULL since we've already drawn it.
  4031. prclBackground = NULL;
  4032. }
  4033. to.vRestoreBkGroundRect();
  4034. }
  4035. // TextOut expects gpos and prfo to be correct so reset them
  4036. to.pwszSet( pwcSave );
  4037. to.prfo = prfoSave;
  4038. return(bRet);
  4039. }
  4040. /******************************Public*Routine*****************************\
  4041. * NtGdiEnableEudc
  4042. *
  4043. * Enable or disable system wide and per-user Eudc information.
  4044. *
  4045. * History:
  4046. * 27-Mar-1996 by Gerrit van Wingerden [gerritv]
  4047. * Wrote it.
  4048. \*************************************************************************/
  4049. extern "C"
  4050. BOOL
  4051. APIENTRY
  4052. NtGdiEnableEudc(
  4053. BOOL bEnable
  4054. )
  4055. {
  4056. return(GreEnableEUDC(bEnable));
  4057. }
  4058. /******************************Public*Routine*****************************\
  4059. * NtGdiEudcLoadUnloadLink
  4060. *
  4061. * Queries system link information
  4062. *
  4063. * History:
  4064. * 27-Mar-1996 by Gerrit van Wingerden [gerritv]
  4065. * Wrote it.
  4066. \*************************************************************************/
  4067. extern "C"
  4068. BOOL
  4069. APIENTRY
  4070. NtGdiEudcLoadUnloadLink(
  4071. LPCWSTR pBaseFaceName,
  4072. UINT cwcBaseFaceName,
  4073. LPCWSTR pEudcFontPath,
  4074. UINT cwcEudcFontPath,
  4075. INT iPriority,
  4076. INT iFontLinkType,
  4077. BOOL bLoadLink)
  4078. {
  4079. WCHAR FaceNameBuffer[LF_FACESIZE+1];
  4080. WCHAR *pPathBuffer;
  4081. BOOL bRet = FALSE;
  4082. if(cwcBaseFaceName > LF_FACESIZE || pEudcFontPath == NULL ||
  4083. (cwcEudcFontPath == 0) || (cwcEudcFontPath > (MAX_PATH+LF_FACESIZE - 1)))
  4084. {
  4085. EngSetLastError(ERROR_INVALID_PARAMETER);
  4086. return(FALSE);
  4087. }
  4088. pPathBuffer = (WCHAR*) AllocFreeTmpBuffer((cwcEudcFontPath+1) * sizeof(WCHAR));
  4089. if(pPathBuffer)
  4090. {
  4091. __try
  4092. {
  4093. if(pBaseFaceName)
  4094. {
  4095. ProbeForRead(pBaseFaceName,cwcBaseFaceName,sizeof(WCHAR));
  4096. RtlCopyMemory(FaceNameBuffer,pBaseFaceName,
  4097. cwcBaseFaceName*sizeof(WCHAR));
  4098. FaceNameBuffer[cwcBaseFaceName] = (WCHAR) 0;
  4099. pBaseFaceName = FaceNameBuffer;
  4100. }
  4101. ProbeForRead(pEudcFontPath,cwcEudcFontPath,sizeof(WCHAR));
  4102. RtlCopyMemory(pPathBuffer,pEudcFontPath,
  4103. cwcEudcFontPath*sizeof(WCHAR));
  4104. pPathBuffer[cwcEudcFontPath] = (WCHAR) 0;
  4105. bRet = TRUE;
  4106. }
  4107. __except(EXCEPTION_EXECUTE_HANDLER)
  4108. {
  4109. WARNINGX(3096);
  4110. }
  4111. if(bRet)
  4112. {
  4113. if(bLoadLink)
  4114. {
  4115. bRet = GreEudcLoadLinkW(pBaseFaceName,
  4116. cwcBaseFaceName,
  4117. pPathBuffer,
  4118. cwcEudcFontPath,
  4119. iPriority,
  4120. iFontLinkType);
  4121. }
  4122. else
  4123. {
  4124. bRet = GreEudcUnloadLinkW(pBaseFaceName,
  4125. cwcBaseFaceName,
  4126. pPathBuffer,
  4127. cwcEudcFontPath);
  4128. }
  4129. }
  4130. FreeTmpBuffer(pPathBuffer);
  4131. }
  4132. return(bRet);
  4133. }
  4134. extern "C"
  4135. UINT
  4136. APIENTRY
  4137. NtGdiGetStringBitmapW(
  4138. HDC hdc,
  4139. LPWSTR pwsz,
  4140. UINT cwc,
  4141. BYTE *lpSB,
  4142. UINT cj
  4143. )
  4144. {
  4145. WCHAR Character;
  4146. LPSTRINGBITMAP OutputBuffer = NULL;
  4147. UINT Status = 1;
  4148. if(cwc != 1)
  4149. {
  4150. return(FALSE);
  4151. }
  4152. if(cj)
  4153. {
  4154. if(!(OutputBuffer = (LPSTRINGBITMAP) AllocFreeTmpBuffer(cj)))
  4155. {
  4156. Status = 0;
  4157. }
  4158. }
  4159. if(Status)
  4160. {
  4161. __try
  4162. {
  4163. ProbeForRead(pwsz,sizeof(WCHAR), sizeof(WCHAR));
  4164. Character = pwsz[0];
  4165. }
  4166. __except(EXCEPTION_EXECUTE_HANDLER)
  4167. {
  4168. WARNINGX(3099);
  4169. Status = 0;
  4170. }
  4171. if(Status)
  4172. {
  4173. Status = GreGetStringBitmapW(hdc,
  4174. &Character,
  4175. 1,
  4176. (LPSTRINGBITMAP) OutputBuffer,
  4177. cj,
  4178. 0);
  4179. }
  4180. if(Status && OutputBuffer)
  4181. {
  4182. __try
  4183. {
  4184. ProbeForWrite(lpSB,cj,sizeof(BYTE));
  4185. RtlCopyMemory(lpSB,OutputBuffer,cj);
  4186. }
  4187. __except(EXCEPTION_EXECUTE_HANDLER)
  4188. {
  4189. WARNINGX(3100);
  4190. Status = 0;
  4191. }
  4192. }
  4193. }
  4194. if(OutputBuffer)
  4195. {
  4196. FreeTmpBuffer(OutputBuffer);
  4197. }
  4198. return Status;
  4199. }
  4200. #endif