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.

1585 lines
47 KiB

  1. /*****************************************************************************
  2. * Module Name: fntcache.cxx
  3. *
  4. * Font Cahce API's for NT font engine.
  5. *
  6. * History:
  7. * 4-15-99 We need to add the code for WTS (Hydra)
  8. * There are 3 major changes,
  9. * (1) We can not write to fntcache.dat in read mode. So we have modified the code
  10. * to make sure there there is no writing to fntcache in read mode.
  11. * (2) Implement a lock algorithm so than no remote session can open the fntcache.dat
  12. * during write mode of console.
  13. * (3) Check the time stamp of win32k.sys and atmfd.dll
  14. * 4-3-98 Yung-Jen Tony Tsai Wrote it.
  15. *
  16. * Copyright (c) 1998-1999 Microsoft Corporation
  17. *****************************************************************************/
  18. #include "precomp.hxx"
  19. #include <ntverp.h>
  20. FLONG gflFntCacheState;
  21. FNTCACHE *gFntCache;
  22. HSEMAPHORE ghsemFntCache = NULL;
  23. extern "C" gbJpn98FixPitch;
  24. extern BOOL G_fConsole;
  25. #define FNTCACHEPATH L"\\SystemRoot\\system32\\FNTCACHE.DAT"
  26. #define WIN32KPATH L"\\SystemRoot\\system32\\win32k.sys"
  27. #define ATMFDPATH L"\\SystemRoot\\system32\\atmfd.dll"
  28. #define DISABLE_REMOTE_FONT_BOOT_CACHE L"DisableRemoteFontBootCache"
  29. #define LASTBOOTTIME_FONT_CACHE_STATE L"LastBootTimeFontCacheState"
  30. #define FNT_CACHE_EXTRA_SIZE (16*512)
  31. #define RESERVE_LINKS 200
  32. #if DBG
  33. VOID DebugGreTrackRemoveMapView(PVOID ViewBase);
  34. #define FNTCACHE_DBG_LEVEL_0 0
  35. #define FNTCACHE_DBG_LEVEL_1 1
  36. #define FNTCACHE_DBG_LEVEL_2 2
  37. #define FNTCACHE_DBG_LEVEL_3 3
  38. ULONG gFntTest = FNTCACHE_DBG_LEVEL_3;
  39. #define FNT_KdBreakPoint(d, s1) \
  40. { \
  41. if (d >= gFntTest) \
  42. { \
  43. DbgPrint s1; \
  44. \
  45. if (d >= FNTCACHE_DBG_LEVEL_1) \
  46. DbgBreakPoint(); \
  47. } \
  48. }
  49. #else
  50. #define FNT_KdBreakPoint(d, s1)
  51. #endif
  52. extern "C" ULONG ComputeFileviewCheckSum(PVOID, ULONG);
  53. #define FNTCacheFileCheckSum(pTableView, cjView) ComputeFileviewCheckSum((PVOID)((PBYTE) pTableView + 4), (cjView -4))
  54. #define FNTINDEX_INVALID 0xffffffff
  55. ULONG ComupteFNTCacheFastCheckSum(ULONG cwc, PWSZ pwsz, PFONTFILEVIEW *ppfv,ULONG cFiles, DESIGNVECTOR *pdv, ULONG cjDV);
  56. VOID SearchFNTCacheHlink(ULONG ulFastCheckSum, FNTHLINK **ppfntHLink, FNTCACHEHEADER *pTable);
  57. BOOL bFntCacheCreateHLink(ULONG ulFastCheckSum);
  58. VOID PutFNTCacheIFI(ULONG ulFastCheckSum, PBYTE pIfi, ULONG ulSize);
  59. FNTHLINK * SearchFntCacheNewLink(ULONG ulFastCheckSum);
  60. BOOL bInitCacheTable(ULONG ulTTFonts, ULONG ulT1FOnts, LARGE_INTEGER FntRegLWT, LARGE_INTEGER T1RegLWT, ULONG CodePage);
  61. // Here is only for performance evaluation
  62. #define KEY_GRE_INITIALIZE L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Gre_Initialize"
  63. #define KEY_NT_CURRENTVERSION L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion"
  64. #define FNT_DISABLEFONTCACHE L"DisableFontBootCache"
  65. #define CURRENT_BUILDNUMBER L"CurrentBuildNumber"
  66. BOOL bQueryValueKey(PWSZ pwszValue, HANDLE RegistryKey, PKEY_VALUE_PARTIAL_INFORMATION ValueKeyInfo, ULONG ValueLength);
  67. BOOL bOpenKey(PWSZ pwszKey, HANDLE *pRegistryKey);
  68. VOID vUnmapFontCacheFile(VOID);
  69. #define EXTRA_BUFFER 48
  70. #define BUFF_LENGTH (sizeof(KEY_VALUE_PARTIAL_INFORMATION) + EXTRA_BUFFER)
  71. typedef union _KVINFO
  72. {
  73. KEY_VALUE_PARTIAL_INFORMATION kv;
  74. BYTE aj[BUFF_LENGTH];
  75. } KVINFO;
  76. VOID vCleanUpFntCache(VOID)
  77. {
  78. if (ghsemFntCache == NULL)
  79. return;
  80. HSEMAPHORE hsemTmp = ghsemFntCache;
  81. {
  82. SEMOBJ so(ghsemFntCache);
  83. if (gFntCache)
  84. {
  85. if (gFntCache->pTable)
  86. {
  87. vUnmapFontCacheFile();
  88. }
  89. VFREEMEM((PVOID) gFntCache);
  90. gFntCache = NULL;
  91. }
  92. gflFntCacheState = 0;
  93. ghsemFntCache = NULL;
  94. }
  95. // delete the semaphore, no longer needed
  96. GreDeleteSemaphore(hsemTmp);
  97. }
  98. BOOL bFntCacheDriverLWT( PCWSTR pcwFontDriverFileName, LARGE_INTEGER *pLastWriteTime)
  99. {
  100. UNICODE_STRING UnicodeString;
  101. OBJECT_ATTRIBUTES ObjectAttributes;
  102. NTSTATUS NtStatus;
  103. HANDLE FileHandle = 0;
  104. IO_STATUS_BLOCK IoStatusBlock;
  105. FILE_BASIC_INFORMATION FileBasicInfo;
  106. BOOL bRet = FALSE;
  107. pLastWriteTime->QuadPart = 0;
  108. RtlInitUnicodeString(&UnicodeString, pcwFontDriverFileName);
  109. InitializeObjectAttributes(
  110. &ObjectAttributes,
  111. &UnicodeString,
  112. OBJ_CASE_INSENSITIVE,
  113. 0,
  114. 0);
  115. NtStatus = IoCreateFile(
  116. &FileHandle,
  117. FILE_GENERIC_READ
  118. | FILE_GENERIC_EXECUTE
  119. | SYNCHRONIZE,
  120. &ObjectAttributes,
  121. &IoStatusBlock,
  122. 0,
  123. FILE_ATTRIBUTE_NORMAL,
  124. FILE_SHARE_READ,
  125. FILE_OPEN, // Flag for file open.
  126. FILE_SYNCHRONOUS_IO_ALERT,
  127. 0,
  128. 0,
  129. CreateFileTypeNone,
  130. NULL,
  131. IO_FORCE_ACCESS_CHECK | // Ensure the user has access to the file
  132. IO_NO_PARAMETER_CHECKING | // All of the buffers are kernel buffers
  133. IO_CHECK_CREATE_PARAMETERS);
  134. if (!NT_SUCCESS(NtStatus))
  135. {
  136. return(FALSE);
  137. }
  138. // Get the time stamp
  139. NtStatus = ZwQueryInformationFile(
  140. FileHandle,
  141. &IoStatusBlock,
  142. &FileBasicInfo,
  143. sizeof(FileBasicInfo),
  144. FileBasicInformation);
  145. ZwClose(FileHandle);
  146. if (NT_SUCCESS(NtStatus))
  147. {
  148. *pLastWriteTime = FileBasicInfo.LastWriteTime;
  149. bRet = TRUE;
  150. }
  151. return bRet;
  152. }
  153. VOID vGetFontDriverLWT(LARGE_INTEGER *pWin32kLWT, LARGE_INTEGER *pAtmfdLWT)
  154. {
  155. LARGE_INTEGER LastWriteTime;
  156. if (bFntCacheDriverLWT( WIN32KPATH, &LastWriteTime))
  157. {
  158. pWin32kLWT->QuadPart = LastWriteTime.QuadPart;
  159. }
  160. if (bFntCacheDriverLWT( ATMFDPATH, &LastWriteTime))
  161. {
  162. pAtmfdLWT->QuadPart = LastWriteTime.QuadPart;
  163. }
  164. }
  165. NTSTATUS GetGreRegKey(HANDLE *phkRegistry, ACCESS_MASK dwDesiredAccess, PCWSTR pcwsz)
  166. {
  167. OBJECT_ATTRIBUTES ObjectAttributes;
  168. UNICODE_STRING UnicodeString;
  169. RtlInitUnicodeString(&UnicodeString, pcwsz);
  170. InitializeObjectAttributes(&ObjectAttributes,
  171. &UnicodeString,
  172. OBJ_CASE_INSENSITIVE,
  173. NULL,
  174. NULL);
  175. return ZwOpenKey(phkRegistry, dwDesiredAccess, &ObjectAttributes);
  176. }
  177. BOOL bSetFntCacheReg(PCWSTR pcwsz, DWORD dwValue)
  178. {
  179. HANDLE hkRegistry;
  180. UNICODE_STRING UnicodeString;
  181. NTSTATUS status;
  182. BOOL bRet = FALSE;
  183. status = GetGreRegKey(&hkRegistry, GENERIC_WRITE, KEY_GRE_INITIALIZE);
  184. if (NT_SUCCESS(status))
  185. {
  186. RtlInitUnicodeString(&UnicodeString, pcwsz);
  187. status = ZwSetValueKey(hkRegistry,
  188. &UnicodeString,
  189. 0,
  190. REG_DWORD,
  191. &dwValue,
  192. sizeof(DWORD));
  193. if (NT_SUCCESS(status))
  194. bRet = TRUE;
  195. else
  196. WARNING(" Failed to set DisableRemoteFontBootCache registry");
  197. ZwCloseKey(hkRegistry);
  198. }
  199. return bRet;
  200. }
  201. DWORD bQueryFntCacheReg (HANDLE hkRegistry, PCWSTR pcwsz, DWORD *pdwDisableMode)
  202. {
  203. UNICODE_STRING UnicodeString;
  204. NTSTATUS status;
  205. DWORD Length;
  206. PKEY_VALUE_FULL_INFORMATION Information;
  207. BOOL bRet = FALSE;
  208. RtlInitUnicodeString(&UnicodeString, pcwsz);
  209. Length = sizeof(KEY_VALUE_FULL_INFORMATION) + (wcslen(pcwsz) + 1) * 2 +
  210. sizeof(DWORD);
  211. Information = (PKEY_VALUE_FULL_INFORMATION) PALLOCMEM(Length, 'CFTT');
  212. if (Information)
  213. {
  214. status = ZwQueryValueKey(hkRegistry,
  215. &UnicodeString,
  216. KeyValueFullInformation,
  217. Information,
  218. Length,
  219. &Length);
  220. if (NT_SUCCESS(status))
  221. {
  222. *pdwDisableMode = *(LPDWORD) ((((PUCHAR)Information) +
  223. Information->DataOffset));
  224. bRet = TRUE;
  225. }
  226. VFREEMEM(Information);
  227. }
  228. return bRet;
  229. }
  230. VOID vGetLastBootTimeStatus(void)
  231. {
  232. HANDLE hkRegistry;
  233. NTSTATUS status;
  234. DWORD dwReg = 0;
  235. status = GetGreRegKey(&hkRegistry, GENERIC_READ, KEY_GRE_INITIALIZE);
  236. gFntCache->flPrevBoot = 0;
  237. if (NT_SUCCESS(status))
  238. {
  239. if (bQueryFntCacheReg(hkRegistry, LASTBOOTTIME_FONT_CACHE_STATE, &dwReg))
  240. {
  241. gFntCache->flPrevBoot = (FLONG) dwReg;
  242. }
  243. ZwCloseKey(hkRegistry);
  244. }
  245. // If we are going to be opening the fntcache.dat in read mode than current boot time state
  246. // will be the same as the previous boot time state. But flThisBoot will change
  247. // if we will be opening the file CREATE (write) mode.
  248. gFntCache->flThisBoot = gFntCache->flPrevBoot;
  249. }
  250. /*****************************************************************************
  251. * BOOL bFntCacheDisabled()
  252. *
  253. * Tempary routine for performance evaluation
  254. *
  255. * History
  256. * 10-15-98 Yung-Jen Tony Tsai [YungT]
  257. * Wrote it.
  258. *****************************************************************************/
  259. BOOL bFntCacheDisabled()
  260. {
  261. HANDLE hkRegistry;
  262. OBJECT_ATTRIBUTES ObjectAttributes;
  263. UNICODE_STRING UnicodeString;
  264. NTSTATUS status;
  265. DWORD Length;
  266. PKEY_VALUE_FULL_INFORMATION Information;
  267. DWORD dwDisableMode = 0;
  268. BOOL bRet = FALSE;
  269. status = GetGreRegKey(&hkRegistry, GENERIC_READ, KEY_GRE_INITIALIZE);
  270. if (NT_SUCCESS(status))
  271. {
  272. // let us check if somebody wanted to disable fontcache.dat by setting the
  273. // DisableFontBootCache in the registry:
  274. if (bQueryFntCacheReg(hkRegistry, L"DisableFontBootCache", &dwDisableMode))
  275. {
  276. if (dwDisableMode)
  277. bRet = TRUE;
  278. }
  279. if (!bRet && !G_fConsole)
  280. {
  281. // we may still want to disable the use of font cache for this remote hydra session.
  282. // We would do this if the console session is writing to the font cache at this time
  283. // (the console session would set the dwDisableMode to 1 in the registry so that
  284. // remote sessions do not try to access the cache)
  285. // or
  286. // if the font cache is in a suspcious state, so that whoever read from or wrote to
  287. // the cache before set the dwDisableMode to 1 in the registry
  288. if (bQueryFntCacheReg(hkRegistry, DISABLE_REMOTE_FONT_BOOT_CACHE, &dwDisableMode))
  289. {
  290. if (dwDisableMode)
  291. bRet = TRUE;
  292. }
  293. else
  294. {
  295. // for some reason, to read the registry failed. So it would be safe to
  296. // disable the font cache.
  297. bRet = TRUE;
  298. }
  299. }
  300. ZwCloseKey(hkRegistry);
  301. }
  302. return bRet;
  303. }
  304. /*****************************************************************************
  305. * BOOL bFntCacheDisabled()
  306. *
  307. * This routine to get the registry only for JPN fix pitch compatible width
  308. *
  309. * History
  310. * 2-3-2000 Yung-Jen Tony Tsai [YungT]
  311. * Wrote it.
  312. *****************************************************************************/
  313. VOID vGetJpn98FixPitch()
  314. {
  315. HANDLE hkRegistry;
  316. NTSTATUS status;
  317. DWORD dwFixPitch = 0;
  318. status = GetGreRegKey(&hkRegistry, GENERIC_READ, KEY_GRE_INITIALIZE);
  319. if (NT_SUCCESS(status))
  320. {
  321. if (bQueryFntCacheReg(hkRegistry, L"Jpn98FixPitch", &dwFixPitch))
  322. {
  323. if (dwFixPitch)
  324. gbJpn98FixPitch = TRUE;
  325. else
  326. gbJpn98FixPitch = FALSE;
  327. }
  328. ZwCloseKey(hkRegistry);
  329. }
  330. }
  331. /*****************************************************************************
  332. * VOID FntCacheHDEV()
  333. *
  334. * Cache the font driver handle, include TT, OT, BMP and VT
  335. *
  336. * History
  337. * 10-15-98 Yung-Jen Tony Tsai [YungT]
  338. * Wrote it.
  339. *****************************************************************************/
  340. VOID FntCacheHDEV(PPDEV hdev, ULONG ulDrv)
  341. {
  342. // There is no cache
  343. if (!(gflFntCacheState & FNT_CACHE_MASK))
  344. {
  345. return;
  346. }
  347. ASSERTGDI (ulDrv && hdev, " Fnt Cache HDEV is wrong \n");
  348. if (ulDrv)
  349. gFntCache->hDev[ulDrv] = hdev;
  350. }
  351. /*****************************************************************************
  352. * extern "C" VOID EngFntCacheFault(ULONG ulFastCheckSum, FLONG fl)
  353. *
  354. * Fault reprot for Engine font cache.
  355. *
  356. * History
  357. * 10-15-98 Yung-Jen Tony Tsai [YungT]
  358. * Wrote it.
  359. *****************************************************************************/
  360. extern "C" VOID EngFntCacheFault(ULONG ulFastCheckSum, FLONG fl)
  361. {
  362. FNTHLINK *pFntHlink = NULL;
  363. BOOL bExcept = FALSE;
  364. // There is no cache
  365. if (ghsemFntCache == NULL)
  366. return;
  367. SEMOBJ so(ghsemFntCache);
  368. if (!(gflFntCacheState & FNT_CACHE_MASK))
  369. {
  370. return;
  371. }
  372. BOOL bUpdate = FALSE;
  373. switch (fl)
  374. {
  375. case ENG_FNT_CACHE_READ_FAULT:
  376. case ENG_FNT_CACHE_WRITE_FAULT:
  377. // if we have already marked the font cache as bad, do not need to do it again
  378. if (!(gFntCache->flThisBoot & FNT_CACHE_STATE_ERROR))
  379. bUpdate = TRUE;
  380. break;
  381. default:
  382. break;
  383. }
  384. if (bUpdate)
  385. {
  386. // we do need to mark the cache invalid
  387. gFntCache->flThisBoot |= FNT_CACHE_STATE_ERROR;
  388. bSetFntCacheReg (LASTBOOTTIME_FONT_CACHE_STATE, gFntCache->flThisBoot);
  389. }
  390. }
  391. /*****************************************************************************
  392. * VOID PutFntCacheDrv(ULONG ulFastCheckSum, PPDEV hdev)
  393. *
  394. * Each font file is mapped to one font driver and cache it.
  395. *
  396. * History
  397. * 10-15-98 Yung-Jen Tony Tsai [YungT]
  398. * Wrote it.
  399. *****************************************************************************/
  400. VOID PutFntCacheDrv(ULONG ulFastCheckSum, PPDEV hdev)
  401. {
  402. if (ghsemFntCache == NULL)
  403. return;
  404. SEMOBJ so(ghsemFntCache);
  405. // There is no cache
  406. if (!(gflFntCacheState & FNT_CACHE_MASK))
  407. {
  408. return;
  409. }
  410. // No checksum mean nothing we can do
  411. if (ulFastCheckSum)
  412. {
  413. ULONG i, ulMode;
  414. ulMode = FNT_DUMMY_DRV;
  415. // Serched the cached device handle
  416. for (i = FNT_TT_DRV; i <= FNT_OT_DRV; i++)
  417. {
  418. if (hdev == gFntCache->hDev[i])
  419. {
  420. ulMode = i;
  421. break;
  422. }
  423. }
  424. // some unknown font driver has been used for the system, and we will not cache it.
  425. if (ulMode == FNT_DUMMY_DRV)
  426. return;
  427. // We cached it when FNTCache is in write mode
  428. if (gflFntCacheState & FNT_CACHE_CREATE_MODE)
  429. {
  430. FNTHLINK *pFntHlink = NULL;
  431. pFntHlink = SearchFntCacheNewLink(ulFastCheckSum);
  432. if (pFntHlink)
  433. {
  434. // If fast check sum is in conflict, we can not cache it.
  435. if (pFntHlink->ulDrvMode == FNT_DUMMY_DRV) // uninitialized link
  436. {
  437. pFntHlink->ulDrvMode = ulMode;
  438. }
  439. else
  440. {
  441. // Ok, fast checksum conflict
  442. WARNING("Checksum conflict in PutFntCacheDrv");
  443. pFntHlink->flLink |= FNT_CACHE_CHECKSUM_CONFLICT;
  444. }
  445. }
  446. else
  447. {
  448. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  449. }
  450. gFntCache->bWrite = TRUE;
  451. }
  452. else
  453. {
  454. ASSERTGDI(gflFntCacheState & FNT_CACHE_LOOKUP_MODE,
  455. "PutFntCacheDrv: gflFntCacheState\n");
  456. // attempting to write during the read mode.
  457. // This may happen if somebody overwrote the file in the fonts directory
  458. // without updating the [Fonts] section in the registry. In this (infrequent) case we
  459. // want to force the rebuild of the cache at the next boot time.
  460. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  461. }
  462. }
  463. }
  464. VOID vUnmapFontCacheFile(VOID)
  465. {
  466. NTSTATUS ntStatus;
  467. ASSERTGDI(gFntCache->pSection, "vUnmapFontCacheFile: gFntCache->pSection is NULL\n");
  468. ASSERTGDI(gFntCache->pTable, "vUnmapFontCacheFile: gFntCache->pTable is NULL\n");
  469. #if defined(_GDIPLUS_)
  470. ntStatus = UnmapViewInProcessSpace(gFntCache->pTable);
  471. #elif defined(_HYDRA_)
  472. // MmUnmapViewInSessionSpace is internally promoted to
  473. // MmUnmapViewInSystemSpace on non-Hydra systems.
  474. ntStatus = Win32UnmapViewInSessionSpace((PVOID) gFntCache->pTable );
  475. #else
  476. ntStatus = MmUnmapViewInSystemSpace((PVOID)gFntCache->pTable)));
  477. #endif
  478. #if DBG
  479. if (!NT_SUCCESS(ntStatus))
  480. RIP(" Font cache file remove Map View failed \n");
  481. #endif
  482. #if DBG && defined(_HYDRA_)
  483. if ((!G_fConsole) && (NT_SUCCESS(ntStatus)))
  484. {
  485. DebugGreTrackRemoveMapView((PVOID) gFntCache->pTable);
  486. }
  487. #endif
  488. DEREFERENCE_FONTVIEW_SECTION(gFntCache->pSection);
  489. gFntCache->pSection = NULL;
  490. gFntCache->pTable = NULL;
  491. return;
  492. }
  493. /*****************************************************************************
  494. * VOID CloseFNTCache()
  495. *
  496. * Clean font cache after system boot
  497. *
  498. * History
  499. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  500. * Wrote it.
  501. *****************************************************************************/
  502. extern "C" VOID CloseFNTCache()
  503. {
  504. // do paranoid check
  505. HSEMAPHORE hsemTmp = ghsemFntCache;
  506. if (ghsemFntCache == NULL)
  507. return;
  508. {
  509. SEMOBJ so(ghsemFntCache);
  510. if (!(gflFntCacheState & FNT_CACHE_MASK))
  511. {
  512. gflFntCacheState = 0;
  513. return;
  514. }
  515. if (gflFntCacheState & FNT_CACHE_CREATE_MODE)
  516. {
  517. // Close the file, we are done recreating it
  518. if (gFntCache->pTable)
  519. {
  520. if (gFntCache->bWrite)
  521. {
  522. gFntCache->pTable->ulTotalLinks = gFntCache->ulCurrentHlink;
  523. gFntCache->pTable->cjDataUsed = (ULONG)(gFntCache->pCacheBuf - gFntCache->pCacheBufStart);
  524. gFntCache->pTable->CheckSum = FNTCacheFileCheckSum(gFntCache->pTable, gFntCache->pTable->ulFileSize);
  525. }
  526. }
  527. }
  528. if (gFntCache->pTable)
  529. {
  530. vUnmapFontCacheFile();
  531. }
  532. // now that the file is closed set the registry to indicate that it is ok for remote
  533. // sessions to read from the cache file
  534. if (gflFntCacheState & FNT_CACHE_CREATE_MODE)
  535. {
  536. if (gFntCache->flPrevBoot != gFntCache->flThisBoot)
  537. bSetFntCacheReg(LASTBOOTTIME_FONT_CACHE_STATE, gFntCache->flThisBoot);
  538. // Unlock fnt cache file, say that it is ok to read from it
  539. bSetFntCacheReg(DISABLE_REMOTE_FONT_BOOT_CACHE, 0);
  540. }
  541. else
  542. {
  543. if (gFntCache->flThisBoot & (FNT_CACHE_STATE_ERROR | FNT_CACHE_STATE_FULL))
  544. bSetFntCacheReg(LASTBOOTTIME_FONT_CACHE_STATE, gFntCache->flThisBoot);
  545. }
  546. VFREEMEM((PVOID) gFntCache);
  547. gFntCache = NULL;
  548. gflFntCacheState = 0;
  549. ghsemFntCache = NULL;
  550. }
  551. // delete the semaphore, no longer needed
  552. GreDeleteSemaphore(hsemTmp);
  553. }
  554. /*****************************************************************************
  555. * BOOL bReAllocCacheFile(ULONG ulSize)
  556. *
  557. * ReAlloc font cache buffer
  558. *
  559. * History
  560. * 10-14-98 modified [YungT]
  561. * 8-22-98 Yung-Jen Tony Tsai [YungT]
  562. * Wrote it.
  563. *****************************************************************************/
  564. BOOL bReAllocCacheFile(ULONG ulSize)
  565. {
  566. BOOL bOK = FALSE;
  567. ULONG ulSizeExtraOrg;
  568. ULONG ulFileSizeOrg;
  569. ULONG ulSizeExtra;
  570. ULONG ulCurrentSize;
  571. ULONG ulFileSize;
  572. DWORD dpOffsetStart;
  573. FILEVIEW FileView;
  574. // OVERFLOW means that we would like to get a bigger cache file but the OS would not give it to us.
  575. // In this case we just close the cache file, update the checksum (bWrite set to true) and
  576. // let remote sessions that are to be started later use the partial cache file
  577. if (gFntCache->flThisBoot & FNT_CACHE_STATE_OVERFLOW)
  578. {
  579. // we tried this once before and it did not work, so we do not bother to do it again
  580. return bOK;
  581. }
  582. ulFileSizeOrg = gFntCache->pTable->ulFileSize;
  583. ulCurrentSize = (ULONG) (gFntCache->pCacheBufEnd - gFntCache->pCacheBuf);
  584. // Calculate the extra cache we need
  585. ulSizeExtra = QWORD_ALIGN(ulSize - ulCurrentSize) + FNT_CACHE_EXTRA_SIZE;
  586. ulFileSize = ulFileSizeOrg + ulSizeExtra;
  587. dpOffsetStart = (DWORD) (gFntCache->pCacheBufStart - (PBYTE) gFntCache->pTable);
  588. if (gFntCache->pTable)
  589. {
  590. vUnmapFontCacheFile();
  591. }
  592. RtlZeroMemory(&FileView, sizeof(FILEVIEW));
  593. if (bMapFile(FNTCACHEPATH, &FileView, ulFileSize, NULL))
  594. {
  595. DWORD dpOffset;
  596. gFntCache->pTable = (FNTCACHEHEADER *) FileView.pvKView;
  597. gFntCache->pSection = FileView.pSection;
  598. gFntCache->pTable->ulFileSize = ulFileSize;
  599. gFntCache->pTable->cjDataExtra += ulSizeExtra;
  600. dpOffset = (ULONG)(gFntCache->pCacheBuf - gFntCache->pCacheBufStart);
  601. // Got a new Table and got to re-calculate the buffer end pointer
  602. gFntCache->pCacheBufStart = (PBYTE) gFntCache->pTable + dpOffsetStart;
  603. gFntCache->pCacheBuf = gFntCache->pCacheBufStart + dpOffset;
  604. gFntCache->pCacheBufEnd = gFntCache->pCacheBufStart + gFntCache->pTable->cjDataAll +
  605. gFntCache->pTable->cjDataExtra;
  606. bOK = TRUE;
  607. }
  608. else
  609. {
  610. // Something wrong, so we do not change anything
  611. RtlZeroMemory(&FileView, sizeof(FILEVIEW));
  612. if (bMapFile(FNTCACHEPATH, &FileView, ulFileSizeOrg, NULL))
  613. {
  614. gFntCache->pTable = (FNTCACHEHEADER *) FileView.pvKView;
  615. gFntCache->pSection = FileView.pSection;
  616. // we want the cache properly closed, with check sum recomputed etc.
  617. gFntCache->bWrite = TRUE;
  618. // Force rebuild on the next boot, but for this boot let remote sessions
  619. // use the partial cache file.
  620. gFntCache->flThisBoot |= (FNT_CACHE_STATE_OVERFLOW | FNT_CACHE_STATE_FULL);
  621. }
  622. else
  623. {
  624. // Something wrong here. We need to set it to no cache mode.
  625. WARNING("bReAllocCacheFile failed to allocate more buffer \n");
  626. gFntCache->flThisBoot |= FNT_CACHE_STATE_ERROR;
  627. }
  628. }
  629. return bOK;
  630. }
  631. /*****************************************************************************
  632. * ULONG QueryFontReg(PWCHAR pwcRegKeyPath, LARGE_INTEGER *pFontRegLastWriteTime)
  633. *
  634. * Helper function for query fonts information from TT and T1 fonts registry
  635. *
  636. * History
  637. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  638. * Wrote it.
  639. *****************************************************************************/
  640. BOOL QueryFontReg(PWCHAR pwcRegKeyPath, LARGE_INTEGER *pFontRegLastWriteTime, ULONG * pulFonts)
  641. {
  642. NTSTATUS Status;
  643. KEY_FULL_INFORMATION KeyInfo;
  644. HANDLE hkey = NULL;
  645. DWORD Length;
  646. *pulFonts = 0;
  647. Status = GetGreRegKey(&hkey,KEY_READ, pwcRegKeyPath);
  648. if (NT_SUCCESS(Status))
  649. {
  650. // get the number of entries in the [Fonts] section and get the last write time
  651. Status = ZwQueryKey(hkey,
  652. KeyFullInformation,
  653. &KeyInfo,
  654. sizeof(KeyInfo),
  655. &Length);
  656. if (NT_SUCCESS(Status))
  657. {
  658. // for additional fonts that do not load from fonts section of the registry
  659. *pulFonts = KeyInfo.Values;
  660. pFontRegLastWriteTime->QuadPart = KeyInfo.LastWriteTime.QuadPart;
  661. FNT_KdBreakPoint(FNTCACHE_DBG_LEVEL_0, (" %d items in Font key \n", *pulFonts));
  662. }
  663. ZwCloseKey(hkey);
  664. }
  665. return NT_SUCCESS(Status);
  666. }
  667. /*****************************************************************************
  668. * PVOID EngFntCacheAlloc(ULONG ulFastCheckSum, ULONG ulSize)
  669. *
  670. * Alloc the cached buffer for font driver
  671. *
  672. * History
  673. * 10-5-98 rewrite [YungT]
  674. * 8-22-98 Yung-Jen Tony Tsai [YungT]
  675. * Wrote it.
  676. *****************************************************************************/
  677. extern "C" PVOID EngFntCacheAlloc(ULONG ulFastCheckSum, ULONG ulSize)
  678. {
  679. PVOID pvIfi = NULL;
  680. {
  681. if (ghsemFntCache == NULL)
  682. return pvIfi;
  683. SEMOBJ so(ghsemFntCache);
  684. if (gflFntCacheState & FNT_CACHE_CREATE_MODE)
  685. {
  686. if ( (gFntCache->pCacheBuf + QWORD_ALIGN(ulSize) < gFntCache->pCacheBufEnd)
  687. || bReAllocCacheFile(ulSize))
  688. {
  689. FNTHLINK *pFntHlink = NULL;
  690. if (pFntHlink = SearchFntCacheNewLink(ulFastCheckSum))
  691. {
  692. // If fast check sum is conflict, we can not cache it.
  693. if (pFntHlink->cjData == 0 && pFntHlink->dpData == 0)
  694. {
  695. pvIfi = (PVOID) gFntCache->pCacheBuf;
  696. // Gaurantee the cache pointer is at 8 byte boundary
  697. gFntCache->pCacheBuf = gFntCache->pCacheBuf + QWORD_ALIGN(ulSize);
  698. pFntHlink->cjData = ulSize;
  699. pFntHlink->dpData = (DWORD) ((PBYTE) pvIfi - gFntCache->pCacheBufStart);
  700. }
  701. else
  702. {
  703. WARNING("Checksum conflict in EngFntCacheAlloc");
  704. pFntHlink->flLink |= FNT_CACHE_CHECKSUM_CONFLICT;
  705. }
  706. gFntCache->bWrite = TRUE;
  707. }
  708. }
  709. }
  710. else
  711. {
  712. ASSERTGDI(gflFntCacheState & FNT_CACHE_LOOKUP_MODE,
  713. "EngFntCacheAlloc: gflFntCacheState\n");
  714. // During read mode, the remote session still wants to write into fntcache.dat.
  715. // This could happen if RemoteSession1 adds more fonts to both registry and on the disk.
  716. // Then later, the RemoteSession2 may attepmpt during its initialization to add these fonts
  717. // to the font cache, but we will reject this and ask that on the next boot the cache file
  718. // be rebuilt. also, the files could have been overwritten on the disk without
  719. // registry entries being updated, so we just force rebuild next time to be safe.
  720. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  721. }
  722. }
  723. if (gFntCache->flThisBoot & FNT_CACHE_STATE_ERROR)
  724. {
  725. CloseFNTCache();
  726. pvIfi = NULL;
  727. }
  728. return pvIfi;
  729. }
  730. /*****************************************************************************
  731. * PVOID EngFntCacheLookUp(ULONG FastCheckSum, ULONG *pcjData)
  732. *
  733. * Lookup font cache
  734. *
  735. * History
  736. * 10-5-98 rewrite [YungT]
  737. * 8-22-98 Yung-Jen Tony Tsai [YungT]
  738. * Wrote it.
  739. *****************************************************************************/
  740. extern "C" PVOID EngFntCacheLookUp(ULONG FastCheckSum, ULONG *pcjData)
  741. {
  742. FNTHLINK *pFntHlink;
  743. PBYTE pCache = NULL;
  744. *pcjData = 0;
  745. pFntHlink = NULL;
  746. if (ghsemFntCache == NULL)
  747. return (PVOID) pCache;
  748. SEMOBJ so(ghsemFntCache);
  749. if (gflFntCacheState & FNT_CACHE_LOOKUP_MODE)
  750. {
  751. if (gFntCache->pTable)
  752. {
  753. // Search the cache table
  754. SearchFNTCacheHlink( FastCheckSum, &pFntHlink, gFntCache->pTable);
  755. if(pFntHlink && !(pFntHlink->flLink & FNT_CACHE_CHECKSUM_CONFLICT))
  756. {
  757. *pcjData = pFntHlink->cjData;
  758. if (*pcjData)
  759. {
  760. pCache = gFntCache->pCacheBufStart + pFntHlink->dpData;
  761. }
  762. }
  763. #if DBG
  764. else
  765. {
  766. if (pFntHlink && (pFntHlink->flLink & FNT_CACHE_CHECKSUM_CONFLICT))
  767. WARNING("Catch the checksum conflict in EngFntCacheLookUp \n");
  768. }
  769. #endif
  770. }
  771. }
  772. return (PVOID) pCache;
  773. }
  774. /*****************************************************************************
  775. * VOID InitNewCacheTable()
  776. *
  777. * Initialize font cache, open the fntcache,dat file and create hash table
  778. *
  779. * History
  780. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  781. * Wrote it.
  782. *****************************************************************************/
  783. BOOL bInitCacheTable(ULONG ulTTFonts, ULONG ulT1Fonts, LARGE_INTEGER FntRegLWT, LARGE_INTEGER T1RegLWT,
  784. LARGE_INTEGER Win32kLWT, LARGE_INTEGER AtmfdLWT, ULONG CodePage)
  785. {
  786. ULONG ulSize, ulIfiSize;
  787. BOOL bOk = FALSE;
  788. ULONG ulMaxFonts;
  789. FILEVIEW FileView;
  790. ulMaxFonts = ulTTFonts + ulT1Fonts + RESERVE_LINKS;
  791. ulSize = SZ_FNTCACHE(ulMaxFonts) + SZ_FNTIFICACHE(ulTTFonts, ulT1Fonts);
  792. if (gFntCache->pTable)
  793. {
  794. vUnmapFontCacheFile();
  795. }
  796. RtlZeroMemory(&FileView, sizeof(FILEVIEW));
  797. if(bMapFile(FNTCACHEPATH, &FileView, ulSize, NULL))
  798. {
  799. gFntCache->pTable = (FNTCACHEHEADER *) FileView.pvKView;
  800. gFntCache->pSection = FileView.pSection;
  801. RtlFillMemory((PBYTE) gFntCache->pTable->aiBuckets,
  802. FNTCACHE_MAX_BUCKETS * sizeof(DWORD), 0xFF);
  803. RtlZeroMemory((PBYTE) gFntCache->pTable->ahlnk,
  804. ulMaxFonts * sizeof(FNTHLINK));
  805. gFntCache->pTable->ulCodePage = (ULONG) CodePage;
  806. gFntCache->pTable->ulMaxFonts = ulMaxFonts;
  807. gFntCache->pTable->ulTotalLinks = 0;
  808. gFntCache->pTable->CheckSum = 0;
  809. gFntCache->pTable->FntRegLWT.QuadPart = FntRegLWT.QuadPart;
  810. gFntCache->pTable->T1RegLWT.QuadPart = T1RegLWT.QuadPart;
  811. gFntCache->pTable->Win32kLWT.QuadPart = Win32kLWT.QuadPart;
  812. gFntCache->pTable->AtmfdLWT.QuadPart = AtmfdLWT.QuadPart;
  813. gFntCache->pTable->ulFileSize = ulSize;
  814. gFntCache->pTable->cjDataAll = SZ_FNTIFICACHE(ulTTFonts, ulT1Fonts);
  815. gFntCache->pTable->cjDataExtra = 0;
  816. gFntCache->pTable->cjDataUsed = 0;
  817. bOk = TRUE;
  818. }
  819. return bOk;
  820. }
  821. /*****************************************************************************
  822. * VOID InitFNTCache()
  823. *
  824. * Initialize font cache, open the fntcache,dat file and create hash table
  825. *
  826. * History
  827. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  828. * Wrote it.
  829. *****************************************************************************/
  830. VOID InitFNTCache()
  831. {
  832. LARGE_INTEGER FntRegLWT = { 0, 0};
  833. LARGE_INTEGER T1RegLWT = { 0, 0};
  834. LARGE_INTEGER Win32kLWT = { 0, 0};
  835. LARGE_INTEGER AtmfdLWT = { 0, 0};
  836. ULONG ulTTFonts = 0;
  837. ULONG ulT1Fonts;
  838. ULONG ulSize = 0;
  839. BOOL bQryFntReg = FALSE;
  840. USHORT AnsiCodePage, OemCodePage;
  841. BOOL bLocked = TRUE;
  842. // Initialize all the global variables
  843. gflFntCacheState = 0;
  844. ghsemFntCache = GreCreateSemaphore();
  845. if (ghsemFntCache == NULL)
  846. {
  847. goto CleanUp;
  848. }
  849. // Only for performance evaluation.
  850. if (bFntCacheDisabled())
  851. {
  852. goto CleanUp;
  853. }
  854. // Initialize and zero out all the memory
  855. gFntCache = (FNTCACHE *) PALLOCMEM(sizeof(FNTCACHE), 'CFTT');
  856. // There is something wrong we can not allocate buf
  857. if (!gFntCache)
  858. {
  859. goto CleanUp;
  860. }
  861. if (G_fConsole)
  862. bLocked = bSetFntCacheReg(DISABLE_REMOTE_FONT_BOOT_CACHE, 1);
  863. // If we can not lock the font cache file,
  864. // then we can not open it in console
  865. if (!bLocked)
  866. {
  867. goto CleanUp;
  868. }
  869. gFntCache->pTable = NULL;
  870. gFntCache->ulCurrentHlink = 0;
  871. gFntCache->hDev[0] = 0;
  872. gFntCache->hDev[1] = 0;
  873. gFntCache->hDev[2] = 0;
  874. gFntCache->hDev[3] = 0;
  875. gFntCache->hDev[4] = 0;
  876. gFntCache->bWrite = FALSE;
  877. RtlGetDefaultCodePage(&AnsiCodePage,&OemCodePage);
  878. // Get the last boot time status
  879. vGetLastBootTimeStatus();
  880. // Get LWT of font driver
  881. vGetFontDriverLWT(&Win32kLWT, &AtmfdLWT);
  882. // now open the TT Fonts key :
  883. if (QueryFontReg(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
  884. &FntRegLWT, &ulTTFonts))
  885. {
  886. ulTTFonts += FNTCACHE_EXTRA_LINKS;
  887. // now open the Type 1 Fonts key :
  888. if (QueryFontReg(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts",
  889. &T1RegLWT, &ulT1Fonts))
  890. {
  891. bQryFntReg = TRUE;
  892. }
  893. }
  894. {
  895. FILEVIEW FileView;
  896. RtlZeroMemory(&FileView, sizeof(FILEVIEW));
  897. if (bMapFile(FNTCACHEPATH, &FileView, 0, NULL))
  898. {
  899. gFntCache->pTable = (FNTCACHEHEADER *) FileView.pvKView;
  900. gFntCache->pSection = (FNTCACHEHEADER *) FileView.pSection;
  901. }
  902. if (gFntCache->pTable)
  903. {
  904. ULONG ulCheckSum;
  905. BOOL bCacheRead;
  906. BOOL bCheckSum;
  907. bCacheRead = FALSE;
  908. bCheckSum = FALSE;
  909. // File did not change from last time boot.
  910. if (gFntCache->pTable->CheckSum && FileView.cjView == gFntCache->pTable->ulFileSize &&
  911. gFntCache->pTable->CheckSum == FNTCacheFileCheckSum(gFntCache->pTable, FileView.cjView) &&
  912. gFntCache->pTable->AtmfdLWT.QuadPart == AtmfdLWT.QuadPart && // current signature of atmfd
  913. gFntCache->pTable->ulCodePage == AnsiCodePage && // If locale changed, we need to re-create the cache
  914. !(gFntCache->flPrevBoot & FNT_CACHE_STATE_ERROR) && // No error at last boot time
  915. (!G_fConsole || // for remote session would not care about the registry update
  916. (!(gFntCache->flPrevBoot & FNT_CACHE_STATE_FULL) &&
  917. gFntCache->pTable->Win32kLWT.QuadPart == Win32kLWT.QuadPart && // check signature of win32k.sys
  918. FntRegLWT.QuadPart == gFntCache->pTable->FntRegLWT.QuadPart && // Check date time of cache file
  919. T1RegLWT.QuadPart == gFntCache->pTable->T1RegLWT.QuadPart
  920. )
  921. )
  922. )
  923. {
  924. gflFntCacheState = FNT_CACHE_LOOKUP_MODE;
  925. }
  926. else
  927. {
  928. if(G_fConsole && bInitCacheTable(ulTTFonts, ulT1Fonts, FntRegLWT, T1RegLWT, Win32kLWT, AtmfdLWT, (ULONG) AnsiCodePage))
  929. {
  930. // If something will not match, then it means we need to create FNTCACHE again
  931. gflFntCacheState = FNT_CACHE_CREATE_MODE;
  932. }
  933. else
  934. {
  935. if (G_fConsole)
  936. {
  937. WARNING(" Boot time Font Cache failed\n");
  938. WARNING(" The pTable is corrupted and font registry is failed to open\n");
  939. }
  940. }
  941. }
  942. }
  943. else
  944. {
  945. // If there is no FNTCACHE.DAT file
  946. // Then we need to create it.
  947. if(G_fConsole && bInitCacheTable(ulTTFonts, ulT1Fonts, FntRegLWT, T1RegLWT, Win32kLWT, AtmfdLWT, (ULONG) AnsiCodePage))
  948. {
  949. gflFntCacheState = FNT_CACHE_CREATE_MODE;
  950. }
  951. else
  952. {
  953. if (G_fConsole)
  954. {
  955. WARNING("Boot time Font Cache failed\n");
  956. WARNING(" If you read this message, please contact YungT or NTFONTS\n");
  957. WARNING(" You can continue without any harm, just hit g\n");
  958. }
  959. }
  960. }
  961. }
  962. CleanUp:
  963. // Semaphore initialized
  964. if (gflFntCacheState & FNT_CACHE_MASK)
  965. {
  966. ASSERTGDI(gFntCache->pTable, "Fnt Cache pTable did not open \n");
  967. // Initialize the start pointer of current Cache table
  968. gFntCache->pCacheBufStart = (PBYTE) gFntCache->pTable +
  969. SZ_FNTCACHE(gFntCache->pTable->ulMaxFonts);
  970. gFntCache->pCacheBuf = gFntCache->pCacheBufStart + gFntCache->pTable->cjDataUsed;
  971. gFntCache->pCacheBufEnd = gFntCache->pCacheBufStart + gFntCache->pTable->cjDataAll +
  972. gFntCache->pTable->cjDataExtra;
  973. gFntCache->ulCurrentHlink = gFntCache->pTable->ulTotalLinks;
  974. if (gflFntCacheState & FNT_CACHE_LOOKUP_MODE)
  975. {
  976. // Unlock the the font cache file to make other session to use it
  977. bSetFntCacheReg(DISABLE_REMOTE_FONT_BOOT_CACHE, 0);
  978. }
  979. else // FNT_CACHE_CREATE_MODE
  980. {
  981. gFntCache->flThisBoot = 0;
  982. }
  983. }
  984. else
  985. {
  986. gflFntCacheState = 0;
  987. // Clean up the memory
  988. if (gFntCache)
  989. {
  990. if (gFntCache->pTable)
  991. {
  992. vUnmapFontCacheFile();
  993. }
  994. VFREEMEM((PVOID) gFntCache);
  995. gFntCache = NULL;
  996. }
  997. if (ghsemFntCache)
  998. {
  999. GreDeleteSemaphore(ghsemFntCache);
  1000. ghsemFntCache = NULL;
  1001. }
  1002. }
  1003. FNT_KdBreakPoint(FNTCACHE_DBG_LEVEL_1, ("FNT Cache Create mode %d\n", gflFntCacheState));
  1004. }
  1005. /*****************************************************************************
  1006. * ULONG ComupteFNTCacheFastCheckSum(ULONG cwc, PWSZ pwsz)
  1007. *
  1008. * Helper function to compute fast checksum
  1009. *
  1010. * History
  1011. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  1012. * Wrote it.
  1013. *****************************************************************************/
  1014. ULONG ComupteFNTCacheFastCheckSum(ULONG cwc, PWSZ pwsz, PFONTFILEVIEW *ppfv,ULONG cFiles, DESIGNVECTOR *pdv, ULONG cjDV)
  1015. {
  1016. ULONG i;
  1017. ULONG checksum = 0;
  1018. USHORT *pusCode;
  1019. for ( i = 0; i < cFiles; i++)
  1020. {
  1021. checksum += (checksum * 256 + ppfv[i]->fv.cjView);
  1022. checksum += (checksum * 256 + (ULONG) ppfv[i]->fv.LastWriteTime.LowPart);
  1023. checksum += (checksum * 256 + (ULONG) ppfv[i]->fv.LastWriteTime.HighPart);
  1024. }
  1025. pusCode = (USHORT *) pwsz;
  1026. for ( i = 0; i < cwc; i++, pusCode++)
  1027. {
  1028. // SUM offset by 1 bit, it will make FastCheckSum unique
  1029. checksum += (checksum * 256 + (ULONG) *pusCode);
  1030. }
  1031. if (pdv && cjDV)
  1032. {
  1033. PULONG pulCur, pulEnd;
  1034. pulCur = (PULONG) pdv;
  1035. for (pulEnd = pulCur + cjDV / sizeof(ULONG); pulCur < pulEnd; pulCur ++)
  1036. {
  1037. checksum += 256 * checksum + *pulCur;
  1038. }
  1039. }
  1040. return checksum;
  1041. }
  1042. /*****************************************************************************
  1043. * ULONG LookUpFNTCacheTable(ULONG cwc, PWSZ pwszPathname, PULONG pulFastCheckSum)
  1044. *
  1045. * Lookup hash table if UFI exist then we return it, otherwise return 0
  1046. *
  1047. * History
  1048. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  1049. * Wrote it.
  1050. *****************************************************************************/
  1051. ULONG LookUpFNTCacheTable(ULONG cwc, PWSZ pwszPathname, PULONG pulFastCheckSum, PFONTFILEVIEW *ppfv, ULONG cFiles, PPDEV * pppDevCache,
  1052. DESIGNVECTOR *pdv, ULONG cjDV)
  1053. {
  1054. ULONG ulUFI = 0;
  1055. ULONG ulBucket = 0;
  1056. FNTHLINK *pFntHlink;
  1057. *pulFastCheckSum = 0;
  1058. *pppDevCache = NULL;
  1059. if (ghsemFntCache == NULL)
  1060. return ulUFI;
  1061. SEMOBJ so(ghsemFntCache);
  1062. if(cwc != 0)
  1063. {
  1064. *pulFastCheckSum = ComupteFNTCacheFastCheckSum ( cwc, pwszPathname, ppfv, cFiles, pdv, cjDV);
  1065. // If in CREATE mode, then nothing is in the cache
  1066. if (gflFntCacheState & FNT_CACHE_LOOKUP_MODE)
  1067. {
  1068. pFntHlink = NULL;
  1069. SearchFNTCacheHlink( *pulFastCheckSum, &pFntHlink, gFntCache->pTable);
  1070. if(pFntHlink && !(pFntHlink->flLink & FNT_CACHE_CHECKSUM_CONFLICT))
  1071. {
  1072. ASSERTGDI( pFntHlink->ulFastCheckSum == *pulFastCheckSum, "ulFastCheckSum != pFntHlink->ulFastCheckSum \n");
  1073. ulUFI = pFntHlink->ulUFI;
  1074. *pppDevCache = gFntCache->hDev[pFntHlink->ulDrvMode];
  1075. }
  1076. }
  1077. }
  1078. return ulUFI;
  1079. }
  1080. /*****************************************************************************
  1081. * VOID SearchFNTCacheHlink(ULONG ulFastCheckSum, FNTHLINK **ppFntHlink)
  1082. *
  1083. * Hash table search function
  1084. *
  1085. * History
  1086. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  1087. * Wrote it.
  1088. *****************************************************************************/
  1089. VOID SearchFNTCacheHlink(ULONG ulFastCheckSum, FNTHLINK **ppFntHlink, FNTCACHEHEADER *pTable)
  1090. {
  1091. // If there is a Cache, then ppFntHlink will not be NULL
  1092. FNTHLINK *pFntHlink;
  1093. *ppFntHlink = NULL;
  1094. ULONG ulHashBucket;
  1095. DWORD iNext;
  1096. // Calculate the hash buckets
  1097. ulHashBucket = ulFastCheckSum % FNTCACHE_MAX_BUCKETS;
  1098. // Start from the first Offset.
  1099. iNext = pTable->aiBuckets[ulHashBucket];
  1100. while (iNext != FNTINDEX_INVALID)
  1101. {
  1102. pFntHlink = &pTable->ahlnk[iNext];
  1103. if (ulFastCheckSum == pFntHlink->ulFastCheckSum)
  1104. {
  1105. *ppFntHlink = pFntHlink;
  1106. break;
  1107. }
  1108. iNext = pFntHlink->iNext;
  1109. }
  1110. return;
  1111. }
  1112. FNTHLINK * SearchFntCacheNewLink(ULONG ulFastCheckSum)
  1113. {
  1114. FNTHLINK *pFntHlink = NULL;
  1115. // Search the new Link from pNewTable
  1116. SearchFNTCacheHlink(ulFastCheckSum, &pFntHlink, gFntCache->pTable);
  1117. // new Link dose not exist, we got to create it from pNewTable
  1118. if (!pFntHlink)
  1119. {
  1120. if (gFntCache->ulCurrentHlink < gFntCache->pTable->ulMaxFonts && bFntCacheCreateHLink(ulFastCheckSum))
  1121. {
  1122. pFntHlink = &gFntCache->pTable->ahlnk[gFntCache->ulCurrentHlink];
  1123. pFntHlink->ulFastCheckSum = ulFastCheckSum;
  1124. pFntHlink->ulUFI = 0;
  1125. pFntHlink->iNext = FNTINDEX_INVALID;
  1126. pFntHlink->cjData = 0;
  1127. pFntHlink->dpData = 0;
  1128. pFntHlink->flLink = 0;
  1129. pFntHlink->ulDrvMode = FNT_DUMMY_DRV;
  1130. gFntCache->ulCurrentHlink++;
  1131. }
  1132. else
  1133. {
  1134. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  1135. }
  1136. }
  1137. return pFntHlink;
  1138. }
  1139. /*****************************************************************************
  1140. * VOID PutFNTCacheCheckSum(ULONG ulFastCheckSum,ULONG ulUFI)
  1141. *
  1142. * Hash table write mode, the UFI does not have in hash and then we put it in.
  1143. *
  1144. * History
  1145. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  1146. * Wrote it.
  1147. *****************************************************************************/
  1148. VOID PutFNTCacheCheckSum(ULONG ulFastCheckSum,ULONG ulUFI)
  1149. {
  1150. FNTHLINK *pFntHlink;
  1151. if (ghsemFntCache == NULL)
  1152. return;
  1153. SEMOBJ so(ghsemFntCache);
  1154. if (gflFntCacheState & FNT_CACHE_CREATE_MODE)
  1155. {
  1156. pFntHlink = NULL;
  1157. if (pFntHlink = SearchFntCacheNewLink(ulFastCheckSum))
  1158. {
  1159. // If fast check sum is conflict, we can not cache it.
  1160. if(pFntHlink->ulUFI == 0)
  1161. {
  1162. pFntHlink->ulUFI = ulUFI;
  1163. }
  1164. else
  1165. {
  1166. WARNING("Checksum conflict in PutFNTCacheCheckSum");
  1167. pFntHlink->flLink |= FNT_CACHE_CHECKSUM_CONFLICT;
  1168. }
  1169. gFntCache->bWrite = TRUE;
  1170. }
  1171. else
  1172. {
  1173. WARNING("FNTCACHE is not big enough \n");
  1174. FNT_KdBreakPoint(FNTCACHE_DBG_LEVEL_1, ("Put Trace: buckets %d, FastCheckSum %x,Check Sum %x \n",
  1175. gFntCache->ulCurrentHlink, ulFastCheckSum, ulUFI));
  1176. }
  1177. }
  1178. else
  1179. {
  1180. ASSERTGDI(gflFntCacheState & FNT_CACHE_LOOKUP_MODE, "PutFNTCacheCheckSum: gflFntCacheState\n");
  1181. // During read mode, it still wants to write into fntcache.dat
  1182. // Then we will rebuild it at next boot time.
  1183. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  1184. }
  1185. }
  1186. /*****************************************************************************
  1187. * void FntCacheCreateHLink
  1188. *
  1189. * Build hash link in hash table
  1190. *
  1191. * History
  1192. * 4-3-98 Yung-Jen Tony Tsai [YungT]
  1193. * Wrote it.
  1194. *****************************************************************************/
  1195. BOOL bFntCacheCreateHLink(ULONG ulFastCheckSum)
  1196. {
  1197. ULONG ulHashBucket;
  1198. FNTHLINK *pCurHlink;
  1199. DWORD iNextLink;
  1200. ulHashBucket = ulFastCheckSum % FNTCACHE_MAX_BUCKETS;
  1201. iNextLink = gFntCache->pTable->aiBuckets[ulHashBucket];
  1202. if (iNextLink != FNTINDEX_INVALID)
  1203. {
  1204. if (iNextLink > gFntCache->pTable->ulMaxFonts)
  1205. return FALSE;
  1206. pCurHlink = &gFntCache->pTable->ahlnk[iNextLink];
  1207. // We put the new link at the end so that the search time is faster
  1208. while (pCurHlink->iNext != FNTINDEX_INVALID)
  1209. {
  1210. if (pCurHlink->iNext > gFntCache->pTable->ulMaxFonts)
  1211. {
  1212. gFntCache->flThisBoot |= FNT_CACHE_STATE_FULL;
  1213. return FALSE;
  1214. }
  1215. pCurHlink = &gFntCache->pTable->ahlnk[pCurHlink->iNext];
  1216. FNT_KdBreakPoint(FNTCACHE_DBG_LEVEL_0, ("Current iNextLink %x\n", pCurHlink->iNext));
  1217. }
  1218. pCurHlink->iNext = gFntCache->ulCurrentHlink;
  1219. }
  1220. else
  1221. {
  1222. // put it at the head of the linked list
  1223. gFntCache->pTable->aiBuckets[ulHashBucket] = gFntCache->ulCurrentHlink;
  1224. FNT_KdBreakPoint(FNTCACHE_DBG_LEVEL_0, ("Put on HashBuckets %x\n", ulHashBucket));
  1225. }
  1226. return TRUE;
  1227. }