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.

1640 lines
44 KiB

  1. /****************************Module*Header******************************\
  2. * Module Name: FIUTILS.C
  3. *
  4. * Module Descripton:
  5. * This file has utility functions that handle NT5 Unidrv font files.
  6. *
  7. * Warnings:
  8. *
  9. * Issues:
  10. *
  11. * Created: 11 November 1997
  12. * Author: Srinivasan Chandrasekar [srinivac]
  13. *
  14. * Copyright (c) 1996, 1997 Microsoft Corporation
  15. \***********************************************************************/
  16. #include "precomp.h"
  17. //
  18. // External functions
  19. //
  20. BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
  21. BOOL WINAPI GetPrinterW(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);;
  22. //
  23. // Internal data structures
  24. //
  25. //
  26. // Structure used to remember which glyph set data's have been written to file
  27. //
  28. typedef struct _FI_GLYPHDATA {
  29. SHORT sGlyphID; // unique glyph ID
  30. WORD wPadding; // set to zero
  31. DWORD gdPos; // position of glyph data inside file
  32. } FI_GLYPHDATA, *PFI_GLYPHDATA;
  33. //
  34. // The handle we pass out is a pointer to this structure
  35. //
  36. typedef struct tagFI_FILE
  37. {
  38. DWORD dwSignature; // Signature of data structure
  39. HANDLE hPrinter; // Handle of printer for using spooler funcs
  40. HANDLE hHeap; // Handle to heap to use
  41. WCHAR wchFileName[MAX_PATH]; // Name of font file
  42. HANDLE hFile; // Handle of open file
  43. PUFF_FILEHEADER pFileHdr; // Pointer to file header
  44. PUFF_FONTDIRECTORY pFontDir; // Pointer to font directory
  45. DWORD dwCurPos; // Current position of write in file
  46. DWORD dwFlags; // Miscellaneous flags
  47. //
  48. // The following are used only if read access is present
  49. //
  50. PBYTE pView; // Pointer to view of file
  51. //
  52. // The following are used only if write access is present
  53. //
  54. PFI_GLYPHDATA pGlyphData; // Pointer to glyphs that have been written
  55. DWORD nGlyphs; // Number of glyphs written
  56. } FI_FILE, *PFI_FILE;
  57. //
  58. // Internal functions
  59. //
  60. #ifdef KERNEL_MODE
  61. HANDLE OpenFontFile(HANDLE, HANDLE, HANDLE, PWSTR);
  62. #else
  63. HANDLE OpenFontFile(HANDLE, HANDLE, PWSTR);
  64. #endif
  65. BOOL WriteData(PFI_FILE, PDATA_HEADER);
  66. void Qsort(PUFF_FONTDIRECTORY, int, int);
  67. void Exchange(PUFF_FONTDIRECTORY, DWORD, DWORD);
  68. BOOL GetFontCartridgeFile(HANDLE, HANDLE);
  69. #define FONT_INFO_SIGNATURE 'fnti'
  70. #define FI_FLAG_READ 0x00000001
  71. #define FI_FLAG_WRITE 0x00000002
  72. #define IsValidFontInfo(pfi) ((pfi) && (pfi)->dwSignature == FONT_INFO_SIGNATURE)
  73. #ifdef KERNEL_MODE
  74. #define ALLOC(hHeap, dwSize) MemAlloc(dwSize)
  75. #define FREE(hHeap, pBuf) MemFree(pBuf)
  76. #else
  77. #define ALLOC(hHeap, dwSize) HeapAlloc((hHeap), HEAP_ZERO_MEMORY, (dwSize))
  78. #define FREE(hHeap, pBuf) HeapFree((hHeap), 0, (pBuf))
  79. #endif
  80. /******************************************************************************
  81. * Functions that handle files that have been opened with read privileges
  82. ******************************************************************************/
  83. /******************************************************************************
  84. *
  85. * FIOpenFontFile
  86. *
  87. * Function:
  88. * This function opens the font file associated with the specified printer
  89. * for read access.
  90. *
  91. * Arguments:
  92. * hPrinter - Handle identifying printer
  93. * hHeap - Handle of heap to use for memory allocations
  94. * bCartridgeFile - Specifies if the font cartridge file is to be opened
  95. * or the currently installed fonts file
  96. *
  97. * Returns:
  98. * Handle to use in subsequent calls if successful, NULL otherwise
  99. *
  100. ******************************************************************************/
  101. HANDLE
  102. FIOpenFontFile(
  103. HANDLE hPrinter,
  104. #ifdef KERNEL_MODE
  105. HANDLE hdev,
  106. #endif
  107. HANDLE hHeap
  108. )
  109. {
  110. #ifdef KERNEL_MODE
  111. return OpenFontFile(hPrinter, hdev, hHeap, REGVAL_FONTFILENAME);
  112. #else
  113. return OpenFontFile(hPrinter, hHeap, REGVAL_FONTFILENAME);
  114. #endif
  115. }
  116. HANDLE
  117. FIOpenCartridgeFile(
  118. HANDLE hPrinter,
  119. #ifdef KERNEL_MODE
  120. HANDLE hdev,
  121. #endif
  122. HANDLE hHeap
  123. )
  124. {
  125. #ifdef KERNEL_MODE
  126. return OpenFontFile(hPrinter, hdev, hHeap, REGVAL_CARTRIDGEFILENAME);
  127. #else
  128. return OpenFontFile(hPrinter, hHeap, REGVAL_CARTRIDGEFILENAME);
  129. #endif
  130. }
  131. HANDLE
  132. OpenFontFile(
  133. HANDLE hPrinter,
  134. #ifdef KERNEL_MODE
  135. HANDLE hdev,
  136. #endif
  137. HANDLE hHeap,
  138. PWSTR pwstrRegVal
  139. )
  140. {
  141. FI_FILE *pFIFile = NULL;
  142. DWORD dwSize, dwStatus, dwType;
  143. BOOL bRc = FALSE;
  144. //
  145. // Allocate FI_FILE structure
  146. //
  147. if (!(pFIFile = (FI_FILE *)ALLOC(hHeap, sizeof(FI_FILE))))
  148. {
  149. WARNING(("Could not allocate memory for opening Font File\n"));
  150. return NULL;
  151. }
  152. pFIFile->dwSignature = FONT_INFO_SIGNATURE;
  153. pFIFile->hPrinter = hPrinter;
  154. pFIFile->hHeap = hHeap;
  155. pFIFile->pView = NULL;
  156. pFIFile->dwFlags = 0;
  157. //
  158. // If we are opening the cartridge file, and we are on the client, get it
  159. // from the server
  160. //
  161. #ifndef KERNEL_MODE
  162. if (wcscmp(pwstrRegVal, REGVAL_CARTRIDGEFILENAME) == 0)
  163. {
  164. if (!BGetFontCartridgeFile(hPrinter, hHeap))
  165. goto EndOpenRead;
  166. }
  167. #endif
  168. //
  169. // Get the name of the font file - strip off the directory path as it may have the
  170. // server path - generate the local path instead
  171. //
  172. {
  173. WCHAR wchFileName[MAX_PATH];
  174. PWSTR pName;
  175. #ifdef KERNEL_MODE
  176. PDRIVER_INFO_3 pdi3;
  177. if (!(pdi3 = MyGetPrinterDriver(hPrinter, hdev, 3)))
  178. goto EndOpenRead;
  179. StringCchCopyW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pdi3->pDriverPath);
  180. MemFree(pdi3);
  181. //
  182. // We have something like "c:\nt\system32\spool\drivers\w32x86\3\unidrv.dll".
  183. // We need only till drivers, so we search backwards for the 3rd '\\'.
  184. //
  185. if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
  186. {
  187. *pName = '\0';
  188. if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
  189. {
  190. *pName = '\0';
  191. if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
  192. *pName = '\0';
  193. }
  194. }
  195. if (!pName)
  196. goto EndOpenRead;
  197. #else
  198. dwSize = sizeof(pFIFile->wchFileName);
  199. if (!GetPrinterDriverDirectoryW(NULL, NULL, 1, (PBYTE)pFIFile->wchFileName, dwSize, &dwSize))
  200. goto EndOpenRead;
  201. //
  202. // Get rid of the processor architecture part
  203. //
  204. if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
  205. *pName = '\0';
  206. #endif
  207. //
  208. // Add "unifont"
  209. //
  210. StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), FONTDIR);
  211. //
  212. // Get font file name from registry
  213. //
  214. dwSize = sizeof(wchFileName);
  215. dwStatus = GetPrinterData(hPrinter, pwstrRegVal, &dwType, (PBYTE)wchFileName, dwSize, &dwSize);
  216. if (dwStatus != ERROR_MORE_DATA && dwStatus != ERROR_SUCCESS)
  217. goto EndOpenRead; // No font file is available
  218. //
  219. // Strip any directory prefix from the font filename
  220. //
  221. if (pName = wcsrchr(wchFileName, '\\'))
  222. pName++;
  223. else
  224. pName = wchFileName;
  225. StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pName);
  226. }
  227. //
  228. // Memory map the file
  229. //
  230. #if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  231. {
  232. PBYTE pTemp = NULL;
  233. DWORD dwSize;
  234. HANDLE hFile;
  235. hFile = MapFileIntoMemory(pFIFile->wchFileName, &pTemp, &dwSize);
  236. if (!pTemp)
  237. {
  238. goto EndOpenRead;
  239. }
  240. pFIFile->pView = ALLOC(hHeap, dwSize);
  241. if (pFIFile->pView)
  242. {
  243. memcpy(pFIFile->pView, pTemp, dwSize);
  244. }
  245. UnmapFileFromMemory((HFILEMAP)hFile);
  246. }
  247. #else
  248. pFIFile->hFile = MapFileIntoMemory(pFIFile->wchFileName, &pFIFile->pView, NULL);
  249. #endif
  250. if (!pFIFile->pView)
  251. {
  252. WARNING(("Err %ld, could not create view of profile %s\n",
  253. GetLastError(), pFIFile->wchFileName));
  254. goto EndOpenRead;
  255. }
  256. //
  257. // Check validity of font file
  258. //
  259. pFIFile->pFileHdr = (PUFF_FILEHEADER)pFIFile->pView;
  260. if (pFIFile->pFileHdr->dwSignature != UFF_FILE_MAGIC ||
  261. pFIFile->pFileHdr->dwVersion != UFF_VERSION_NUMBER ||
  262. pFIFile->pFileHdr->dwSize != sizeof(UFF_FILEHEADER))
  263. {
  264. WARNING(("Invalid font file %s\n", pFIFile->wchFileName));
  265. goto EndOpenRead;
  266. }
  267. //
  268. // Set other fields
  269. //
  270. if (pFIFile->pFileHdr->offFontDir)
  271. {
  272. pFIFile->pFontDir = (PUFF_FONTDIRECTORY)(pFIFile->pView + pFIFile->pFileHdr->offFontDir);
  273. }
  274. pFIFile->dwCurPos = 0;
  275. pFIFile->dwFlags = FI_FLAG_READ;
  276. pFIFile->pGlyphData = NULL;
  277. pFIFile->nGlyphs = 0;
  278. bRc = TRUE;
  279. EndOpenRead:
  280. if (!bRc)
  281. {
  282. FICloseFontFile((HANDLE)pFIFile);
  283. pFIFile = NULL;
  284. }
  285. return (HANDLE)pFIFile;
  286. }
  287. /******************************************************************************
  288. *
  289. * FICloseFontFile
  290. *
  291. * Function:
  292. * This function closes the given font file and frees all memory
  293. * associated with it
  294. *
  295. * Arguments:
  296. * hFontFile - Handle identifying font file to close
  297. *
  298. * Returns:
  299. * Nothing
  300. *
  301. ******************************************************************************/
  302. VOID
  303. FICloseFontFile(
  304. HANDLE hFontFile
  305. )
  306. {
  307. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  308. if (IsValidFontInfo(pFIFile))
  309. {
  310. if (pFIFile->dwFlags & FI_FLAG_READ)
  311. {
  312. //
  313. // Memory mapped file was opened, close it
  314. //
  315. if (pFIFile->pView)
  316. {
  317. #if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
  318. FREE(pFIFile->hHeap, pFIFile->pView);
  319. #else
  320. UnmapFileFromMemory((HFILEMAP)pFIFile->hFile);
  321. #endif
  322. }
  323. }
  324. #ifndef KERNEL_MODE
  325. else
  326. {
  327. //
  328. // New file was created, free all allocated memory
  329. //
  330. if (pFIFile->pFileHdr)
  331. {
  332. FREE(pFIFile->hHeap, pFIFile->pFileHdr);
  333. }
  334. if (pFIFile->pFontDir)
  335. {
  336. FREE(pFIFile->hHeap, pFIFile->pFontDir);
  337. }
  338. if (pFIFile->hFile != INVALID_HANDLE_VALUE)
  339. {
  340. CloseHandle(pFIFile->hFile);
  341. }
  342. if (pFIFile->pGlyphData)
  343. {
  344. FREE(pFIFile->hHeap, pFIFile->pGlyphData);
  345. }
  346. }
  347. #endif
  348. FREE(pFIFile->hHeap, pFIFile);
  349. }
  350. return;
  351. }
  352. /******************************************************************************
  353. *
  354. * FIGetNumFonts
  355. *
  356. * Function:
  357. * This function retrieves the number of fonts present in the given
  358. * font file
  359. *
  360. * Arguments:
  361. * hFontFile - Handle identifying font file
  362. *
  363. * Returns:
  364. * Number of font present if successful, 0 otherwise
  365. *
  366. ******************************************************************************/
  367. DWORD
  368. FIGetNumFonts(
  369. HANDLE hFontFile
  370. )
  371. {
  372. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  373. return IsValidFontInfo(pFIFile) ? pFIFile->pFileHdr->nFonts : 0;
  374. }
  375. /******************************************************************************
  376. *
  377. * FIGetFontDir
  378. *
  379. * Function:
  380. * This function retrieves a pointer to the font directory of the
  381. * given font file
  382. *
  383. * Arguments:
  384. * hFontFile - Handle identifying font file
  385. *
  386. * Returns:
  387. * Pointer to font directory if successful, NULL otherwise
  388. *
  389. ******************************************************************************/
  390. PUFF_FONTDIRECTORY
  391. FIGetFontDir(
  392. HANDLE hFontFile
  393. )
  394. {
  395. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  396. return IsValidFontInfo(pFIFile) ? pFIFile->pFontDir : NULL;
  397. }
  398. /******************************************************************************
  399. *
  400. * FIGetFontName
  401. *
  402. * Function:
  403. * This function retrieves a pointer to the name of the iFontIndex'th font
  404. * in the given font file
  405. *
  406. * Arguments:
  407. * hFontFile - Handle identifying font file
  408. * iFontIndex - Index of the font whose name is to be retrieved
  409. *
  410. * Returns:
  411. * Pointer to font name if successful, NULL otherwise
  412. *
  413. ******************************************************************************/
  414. PWSTR
  415. FIGetFontName(
  416. HANDLE hFontFile,
  417. DWORD iFontIndex
  418. )
  419. {
  420. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  421. PWSTR pwstrFontName = NULL;
  422. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
  423. {
  424. if (iFontIndex < pFIFile->pFileHdr->nFonts)
  425. {
  426. pwstrFontName = (PWSTR)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offFontName);
  427. }
  428. }
  429. return pwstrFontName;
  430. }
  431. /******************************************************************************
  432. *
  433. * FIGetFontCartridgeName
  434. *
  435. * Function:
  436. * This function retrieves a pointer to the name of the iFontIndex'th font
  437. * cartridge in the given font file
  438. *
  439. * Arguments:
  440. * hFontFile - Handle identifying font file
  441. * iFontIndex - Index of the font whose cartridge name is to be retrieved
  442. *
  443. * Returns:
  444. * Pointer to font cartridge name if present, NULL otherwise
  445. *
  446. ******************************************************************************/
  447. PWSTR
  448. FIGetFontCartridgeName(
  449. HANDLE hFontFile,
  450. DWORD iFontIndex
  451. )
  452. {
  453. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  454. PWSTR pwstrCartridgeName = NULL;
  455. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
  456. {
  457. if (iFontIndex < pFIFile->pFileHdr->nFonts)
  458. {
  459. pwstrCartridgeName = pFIFile->pFontDir[iFontIndex].offCartridgeName ?
  460. (PWSTR)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offCartridgeName) : NULL;
  461. }
  462. }
  463. return pwstrCartridgeName;
  464. }
  465. /******************************************************************************
  466. *
  467. * FIGetFontData
  468. *
  469. * Function:
  470. * This function retrieves a pointer to the font data for the
  471. * iFontIndex'th font in the given font file
  472. *
  473. * Arguments:
  474. * hFontFile - Handle identifying font file
  475. * iFontIndex - Index of the font whose font data is to be retrieved
  476. *
  477. * Returns:
  478. * Pointer to font data if successful, NULL otherwise
  479. *
  480. ******************************************************************************/
  481. PDATA_HEADER
  482. FIGetFontData(
  483. HANDLE hFontFile,
  484. DWORD iFontIndex
  485. )
  486. {
  487. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  488. PDATA_HEADER pData = NULL;
  489. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
  490. {
  491. if (iFontIndex < pFIFile->pFileHdr->nFonts)
  492. {
  493. pData = (PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offFontData);
  494. }
  495. }
  496. return pData;
  497. }
  498. /******************************************************************************
  499. *
  500. * FIGetGlyphData
  501. *
  502. * Function:
  503. * This function retrieves a pointer to the glyph data for the
  504. * iFontIndex'th font in the given font file
  505. *
  506. * Arguments:
  507. * hFontFile - Handle identifying font file
  508. * iFontIndex - Index of the font whose glyph data is to be retrieved
  509. *
  510. * Returns:
  511. * Pointer to glyph data if successful, NULL otherwise
  512. *
  513. ******************************************************************************/
  514. PDATA_HEADER
  515. FIGetGlyphData(
  516. HANDLE hFontFile,
  517. DWORD iFontIndex
  518. )
  519. {
  520. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  521. PDATA_HEADER pData = NULL;
  522. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
  523. {
  524. if (iFontIndex < pFIFile->pFileHdr->nFonts)
  525. {
  526. pData = pFIFile->pFontDir[iFontIndex].offGlyphData ?
  527. (PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offGlyphData) : NULL;
  528. }
  529. }
  530. return pData;
  531. }
  532. /******************************************************************************
  533. *
  534. * FIGetVarData
  535. *
  536. * Function:
  537. * This function retrieves a pointer to the variable data for the
  538. * iFontIndex'th font in the given font file
  539. *
  540. * Arguments:
  541. * hFontFile - Handle identifying font file
  542. * iFontIndex - Index of the font whose variable data is to be retrieved
  543. *
  544. * Returns:
  545. * Pointer to variable data if present, NULL otherwise
  546. *
  547. ******************************************************************************/
  548. PDATA_HEADER
  549. FIGetVarData(
  550. HANDLE hFontFile,
  551. DWORD iFontIndex
  552. )
  553. {
  554. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  555. PDATA_HEADER pData = NULL;
  556. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
  557. {
  558. if (iFontIndex < pFIFile->pFileHdr->nFonts)
  559. {
  560. pData = pFIFile->pFontDir[iFontIndex].offVarData ?
  561. (PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offVarData) : NULL;
  562. }
  563. }
  564. return pData;
  565. }
  566. #ifndef KERNEL_MODE
  567. /******************************************************************************
  568. * Functions that handle files that have been opened with write privileges
  569. ******************************************************************************/
  570. /******************************************************************************
  571. *
  572. * FICreateFontFile
  573. *
  574. * Function:
  575. * This function creates a new font file with only write access.
  576. *
  577. * Arguments:
  578. * hPrinter - Handle identifying printer
  579. * hHeap - Handle of heap to use for memory allocations
  580. *
  581. * Returns:
  582. * Handle to use in subsequent calls if successful, NULL otherwise
  583. *
  584. ******************************************************************************/
  585. HANDLE
  586. FICreateFontFile(
  587. HANDLE hPrinter,
  588. HANDLE hHeap,
  589. DWORD cFonts
  590. )
  591. {
  592. FI_FILE *pFIFile = NULL;
  593. PWSTR pName, pstrGuid;
  594. DWORD dwSize;
  595. UUID guid;
  596. BOOL bRc = FALSE;
  597. //
  598. // Allocate FI_FILE structure
  599. //
  600. if (!(pFIFile = (FI_FILE *)ALLOC(hHeap, sizeof(FI_FILE))))
  601. {
  602. WARNING(("Could not allocate memory for creating Font File\n"));
  603. return NULL;
  604. }
  605. pFIFile->dwSignature = FONT_INFO_SIGNATURE;
  606. pFIFile->hPrinter = hPrinter;
  607. pFIFile->hHeap = hHeap;
  608. //
  609. // Generate file name for font file
  610. //
  611. dwSize = sizeof(pFIFile->wchFileName);
  612. if (!GetPrinterDriverDirectoryW(NULL, NULL, 1, (PBYTE)pFIFile->wchFileName, dwSize, &dwSize))
  613. {
  614. WARNING(("Error getting printer driver directory"));
  615. goto EndCreateNew;
  616. }
  617. //
  618. // Get rid of the processor architecture part
  619. //
  620. if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
  621. *pName = '\0';
  622. //
  623. // Add "unifont"
  624. //
  625. StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), FONTDIR);
  626. //
  627. // Make sure the local directory is created
  628. //
  629. if ( ! CreateDirectory(pFIFile->wchFileName, NULL) )
  630. {
  631. WARNING(("Error creating directory %s", pFIFile->wchFileName));
  632. goto EndCreateNew;
  633. }
  634. if ((UuidCreate(&guid) != RPC_S_OK) ||
  635. (UuidToString(&guid, &pstrGuid) != RPC_S_OK))
  636. {
  637. WARNING(("Error getting a guid string\n"));
  638. goto EndCreateNew;
  639. }
  640. StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pstrGuid);
  641. StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), L".UFF");
  642. RpcStringFree(&pstrGuid);
  643. pFIFile->hFile = CreateFile(pFIFile->wchFileName,
  644. GENERIC_WRITE,
  645. 0,
  646. NULL,
  647. CREATE_ALWAYS,
  648. FILE_FLAG_RANDOM_ACCESS | SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
  649. NULL);
  650. if (pFIFile->hFile == INVALID_HANDLE_VALUE)
  651. {
  652. WARNING(("Error creating file %s", pFIFile->wchFileName));
  653. goto EndCreateNew;
  654. }
  655. //
  656. // Set other fields
  657. //
  658. pFIFile->dwFlags = FI_FLAG_WRITE; // Give write access alone
  659. pFIFile->dwCurPos = 0;
  660. //
  661. // Allocate memory for remembering glyph datas that have been written.
  662. // Max memory needed is if each font has a different glyph data.
  663. //
  664. pFIFile->pGlyphData = (PFI_GLYPHDATA)ALLOC(hHeap, cFonts * sizeof(FI_GLYPHDATA));
  665. if (!pFIFile->pGlyphData)
  666. {
  667. WARNING(("Error allocating memory for tracking glyph data\n"));
  668. goto EndCreateNew;
  669. }
  670. pFIFile->nGlyphs = 0;
  671. //
  672. // Allocate memory for the file header and font directory
  673. //
  674. pFIFile->pFileHdr = (PUFF_FILEHEADER)ALLOC(hHeap, sizeof(UFF_FILEHEADER));
  675. pFIFile->pFontDir = (PUFF_FONTDIRECTORY)ALLOC(hHeap, cFonts * sizeof(UFF_FONTDIRECTORY));
  676. if (!pFIFile->pFileHdr || !pFIFile->pFontDir)
  677. {
  678. WARNING(("Error allocating memory for file header or font directory\n"));
  679. goto EndCreateNew;
  680. }
  681. //
  682. // Initialize file header
  683. //
  684. pFIFile->pFileHdr->dwSignature = UFF_FILE_MAGIC;
  685. pFIFile->pFileHdr->dwVersion = UFF_VERSION_NUMBER;
  686. pFIFile->pFileHdr->dwSize = sizeof(UFF_FILEHEADER);
  687. pFIFile->pFileHdr->nFonts = cFonts;
  688. if (cFonts)
  689. {
  690. pFIFile->pFileHdr->offFontDir = sizeof(UFF_FILEHEADER);
  691. }
  692. bRc = TRUE;
  693. EndCreateNew:
  694. if (!bRc)
  695. {
  696. FICloseFontFile((HANDLE)pFIFile);
  697. pFIFile = NULL;
  698. }
  699. return (HANDLE)pFIFile;
  700. }
  701. /******************************************************************************
  702. *
  703. * FIWriteFileHeader
  704. *
  705. * Function:
  706. * This function seeks to the beginning of the file and writes the
  707. * file header
  708. *
  709. * Arguments:
  710. * hFontFile - Handle identifying font file
  711. *
  712. * Returns:
  713. * TRUE if successful, FALSE otherwise
  714. *
  715. ******************************************************************************/
  716. BOOL
  717. FIWriteFileHeader(
  718. HANDLE hFontFile
  719. )
  720. {
  721. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  722. DWORD dwSize;
  723. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
  724. {
  725. if (pFIFile->dwCurPos != 0)
  726. {
  727. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, 0, 0, FILE_BEGIN);
  728. }
  729. if (!WriteFile(pFIFile->hFile, (PVOID)pFIFile->pFileHdr, sizeof(UFF_FILEHEADER), &dwSize, NULL))
  730. {
  731. return FALSE;
  732. }
  733. pFIFile->dwCurPos += dwSize;
  734. }
  735. return TRUE;
  736. }
  737. /******************************************************************************
  738. *
  739. * FIWriteFontDirectory
  740. *
  741. * Function:
  742. * This function seeks to the right place in the file and writes the
  743. * font directory. It sorts it by font ID if it is not already sorted.
  744. *
  745. * Arguments:
  746. * hFontFile - Handle identifying font file
  747. *
  748. * Returns:
  749. * TRUE if successful, FALSE otherwise
  750. *
  751. ******************************************************************************/
  752. BOOL
  753. FIWriteFontDirectory(
  754. HANDLE hFontFile
  755. )
  756. {
  757. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  758. DWORD dwSize;
  759. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
  760. {
  761. //
  762. // If there are no fonts, there is nothing to write
  763. //
  764. if (pFIFile->pFileHdr->offFontDir == 0)
  765. return TRUE;
  766. //
  767. // Seek to right place
  768. //
  769. if (pFIFile->dwCurPos != pFIFile->pFileHdr->offFontDir)
  770. {
  771. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->pFileHdr->offFontDir, 0, FILE_BEGIN);
  772. }
  773. //
  774. // Sort the font directory
  775. //
  776. Qsort(pFIFile->pFontDir, (int)0, (int)pFIFile->pFileHdr->nFonts-1);
  777. pFIFile->pFileHdr->dwFlags |= FONT_DIR_SORTED;
  778. if (!WriteFile(pFIFile->hFile, (PVOID)pFIFile->pFontDir, pFIFile->pFileHdr->nFonts*sizeof(UFF_FONTDIRECTORY), &dwSize, NULL))
  779. {
  780. return FALSE;
  781. }
  782. pFIFile->dwCurPos += dwSize;
  783. }
  784. return TRUE;
  785. }
  786. /******************************************************************************
  787. *
  788. * FIAlignedSeek
  789. *
  790. * Function:
  791. * This function seeks forward by the specified amount and then some if
  792. * required so you end up DWORD aligned
  793. *
  794. * Arguments:
  795. * hFontFile - Handle identifying font file
  796. * lSeekDist - Amount to seek forward by
  797. *
  798. * Returns:
  799. * Handle to use in subsequent calls if successful, NULL otherwise
  800. *
  801. ******************************************************************************/
  802. VOID
  803. FIAlignedSeek(
  804. HANDLE hFontFile,
  805. DWORD dwSeekDist
  806. )
  807. {
  808. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  809. if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
  810. {
  811. pFIFile->dwCurPos += dwSeekDist;
  812. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3; // DWORD align
  813. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  814. }
  815. return;
  816. }
  817. /******************************************************************************
  818. *
  819. * FICopyFontRecord
  820. *
  821. * Function:
  822. * This function copies a font record including the directory entry,
  823. * font meetrics, glyph data and variable data from one font file
  824. * to another.
  825. *
  826. * Arguments:
  827. * hWriteFile - Handle identifying font file to write into
  828. * hReadFile - Handle identifying font file to read from
  829. * dwWrIndex - Index of font to write into in write file
  830. * dwRdIndex - Index of font to read from in read file
  831. *
  832. * Returns:
  833. * TRUE if successful, FALSE otherwise
  834. *
  835. ******************************************************************************/
  836. BOOL
  837. FICopyFontRecord(
  838. HANDLE hWriteFile,
  839. HANDLE hReadFile,
  840. DWORD dwWrIndex,
  841. DWORD dwRdIndex
  842. )
  843. {
  844. FI_FILE *pFIWrFile = (FI_FILE*)hWriteFile;
  845. FI_FILE *pFIRdFile = (FI_FILE*)hReadFile;
  846. PDATA_HEADER pData;
  847. PWSTR pName;
  848. DWORD dwSize;
  849. DWORD j, gdPos;
  850. if (!IsValidFontInfo(pFIWrFile) ||
  851. !IsValidFontInfo(pFIRdFile) ||
  852. !(pFIWrFile->dwFlags & FI_FLAG_WRITE) ||
  853. !(pFIRdFile->dwFlags & FI_FLAG_READ))
  854. {
  855. return FALSE;
  856. }
  857. //
  858. // Copy the font directory entry
  859. //
  860. pFIWrFile->pFontDir[dwWrIndex].dwSignature = FONT_REC_SIG;
  861. pFIWrFile->pFontDir[dwWrIndex].wSize = (WORD)sizeof(UFF_FONTDIRECTORY);
  862. pFIWrFile->pFontDir[dwWrIndex].wFontID = (WORD)dwWrIndex;
  863. pFIWrFile->pFontDir[dwWrIndex].sGlyphID = pFIRdFile->pFontDir[dwRdIndex].sGlyphID;
  864. pFIWrFile->pFontDir[dwWrIndex].wFlags = pFIRdFile->pFontDir[dwRdIndex].wFlags;
  865. pFIWrFile->pFontDir[dwWrIndex].dwInstallerSig = pFIRdFile->pFontDir[dwRdIndex].dwInstallerSig;
  866. //
  867. // Write font name
  868. //
  869. pName = FIGetFontName(hReadFile, dwRdIndex);
  870. ASSERT(pName != NULL); // Can't have NULL font name
  871. if (NULL == pName)
  872. {
  873. return FALSE;
  874. }
  875. pFIWrFile->pFontDir[dwWrIndex].offFontName = pFIWrFile->dwCurPos;
  876. if (!WriteFile(pFIWrFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
  877. {
  878. WARNING(("Error writing font name\n"));
  879. return FALSE;
  880. }
  881. pFIWrFile->dwCurPos += dwSize;
  882. pFIWrFile->dwCurPos = (pFIWrFile->dwCurPos + 3) & ~3;
  883. pFIWrFile->dwCurPos = SetFilePointer(pFIWrFile->hFile, pFIWrFile->dwCurPos, 0, FILE_BEGIN);
  884. //
  885. // Write font cartridge name
  886. //
  887. pName = FIGetFontCartridgeName(hReadFile, dwRdIndex);
  888. if (pName == NULL)
  889. {
  890. pFIWrFile->pFontDir[dwRdIndex].offCartridgeName = 0;
  891. }
  892. else
  893. {
  894. pFIWrFile->pFontDir[dwWrIndex].offCartridgeName = pFIWrFile->dwCurPos;
  895. if (!WriteFile(pFIWrFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
  896. {
  897. WARNING(("Error writing font cartridge name\n"));
  898. return FALSE;
  899. }
  900. pFIWrFile->dwCurPos += dwSize;
  901. pFIWrFile->dwCurPos = (pFIWrFile->dwCurPos + 3) & ~3;
  902. pFIWrFile->dwCurPos = SetFilePointer(pFIWrFile->hFile, pFIWrFile->dwCurPos, 0, FILE_BEGIN);
  903. }
  904. //
  905. // Write font data
  906. //
  907. pData = FIGetFontData(hReadFile, dwRdIndex);
  908. ASSERT(pData != NULL); // Can't have NULL font data
  909. pFIWrFile->pFontDir[dwWrIndex].offFontData = pFIWrFile->dwCurPos;
  910. if (!WriteData(pFIWrFile, pData))
  911. return FALSE;
  912. //
  913. // Get glyph data from read file
  914. //
  915. pData = FIGetGlyphData(pFIRdFile, dwRdIndex);
  916. if (pData)
  917. {
  918. //
  919. // Check if it is already in write file
  920. //
  921. gdPos = 0;
  922. for (j=0; j<pFIWrFile->nGlyphs; j++)
  923. {
  924. if (pFIWrFile->pGlyphData[j].sGlyphID == pFIWrFile->pFontDir[dwWrIndex].sGlyphID)
  925. {
  926. gdPos = pFIWrFile->pGlyphData[j].gdPos;
  927. }
  928. }
  929. if (gdPos == 0)
  930. {
  931. //
  932. // Not there yet - add to set of glyph data's that have been
  933. // added to file, and write it into write file
  934. //
  935. pFIWrFile->pGlyphData[pFIWrFile->nGlyphs].sGlyphID = pFIWrFile->pFontDir[dwWrIndex].sGlyphID;
  936. pFIWrFile->pGlyphData[pFIWrFile->nGlyphs].gdPos = pFIWrFile->dwCurPos;
  937. pFIWrFile->nGlyphs++;
  938. pFIWrFile->pFontDir[dwWrIndex].offGlyphData = pFIWrFile->dwCurPos;
  939. if (!WriteData(pFIWrFile, pData))
  940. return FALSE;
  941. pFIWrFile->pFileHdr->nGlyphSets++;
  942. }
  943. else
  944. {
  945. //
  946. // Already in file, just update location
  947. //
  948. pFIWrFile->pFontDir[dwWrIndex].offGlyphData = gdPos;
  949. }
  950. }
  951. else
  952. {
  953. //
  954. // Glyph data not present
  955. //
  956. pFIWrFile->pFontDir[dwWrIndex].offGlyphData = 0;
  957. }
  958. //
  959. // Write var data
  960. //
  961. pData = FIGetVarData(pFIRdFile, dwRdIndex);
  962. if (pData)
  963. {
  964. pFIWrFile->pFontDir[dwWrIndex].offVarData = pFIWrFile->dwCurPos;
  965. if (!WriteData(pFIWrFile, pData))
  966. return FALSE;
  967. pFIWrFile->pFileHdr->nVarData++;
  968. }
  969. else
  970. pFIWrFile->pFontDir[dwWrIndex].offVarData = 0;
  971. return TRUE;
  972. }
  973. /******************************************************************************
  974. *
  975. * FIAddFontRecord
  976. *
  977. * Function:
  978. * This function adds a font record including the directory entry,
  979. * font meetrics, glyph data and variable data
  980. *
  981. * Arguments:
  982. * hFontFile - Handle identifying font file to write
  983. * dwIndex - Index of font to write
  984. * pFntDat - Information about font to add
  985. *
  986. * Returns:
  987. * TRUE if successful, FALSE otherwise
  988. *
  989. ******************************************************************************/
  990. BOOL
  991. FIAddFontRecord(
  992. HANDLE hFontFile,
  993. DWORD dwIndex,
  994. FNTDAT *pFntDat
  995. )
  996. {
  997. FI_FILE *pFIFile = (FI_FILE*)hFontFile;
  998. PDATA_HEADER pData;
  999. PWSTR pName;
  1000. DWORD dwSize;
  1001. DWORD j, gdPos;
  1002. if (!IsValidFontInfo(pFIFile) ||
  1003. !(pFIFile->dwFlags & FI_FLAG_WRITE))
  1004. {
  1005. return FALSE;
  1006. }
  1007. //
  1008. // Initialize the font directory entry
  1009. //
  1010. pFIFile->pFontDir[dwIndex].dwSignature = FONT_REC_SIG;
  1011. pFIFile->pFontDir[dwIndex].wSize = sizeof(UFF_FONTDIRECTORY);
  1012. pFIFile->pFontDir[dwIndex].wFontID = (WORD)dwIndex;
  1013. pFIFile->pFontDir[dwIndex].sGlyphID = (short)pFntDat->fid.dsCTT.cBytes;
  1014. pFIFile->pFontDir[dwIndex].wFlags = FONT_FL_SOFTFONT | FONT_FL_IFI | FONT_FL_GLYPHSET_RLE;
  1015. pFIFile->pFontDir[dwIndex].dwInstallerSig = WINNT_INSTALLER_SIG;
  1016. //
  1017. // Write font name
  1018. //
  1019. pName = pFntDat->fid.dsIdentStr.pvData;
  1020. ASSERT(pName != NULL); // Can't have NULL font name
  1021. pFIFile->pFontDir[dwIndex].offFontName = pFIFile->dwCurPos;
  1022. if (!WriteFile(pFIFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
  1023. {
  1024. WARNING(("Error writing font name\n"));
  1025. return FALSE;
  1026. }
  1027. pFIFile->dwCurPos += dwSize;
  1028. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
  1029. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  1030. //
  1031. // No font cartridge name
  1032. //
  1033. pFIFile->pFontDir[dwIndex].offCartridgeName = 0;
  1034. //
  1035. // Write font data
  1036. //
  1037. pFIFile->pFontDir[dwIndex].offFontData = pFIFile->dwCurPos;
  1038. if ((dwSize = FIWriteFix(pFIFile->hFile, (WORD)dwIndex, &pFntDat->fid)) == 0)
  1039. {
  1040. WARNING(("Error writing fixed part of font data\n"));
  1041. return FALSE;
  1042. }
  1043. pFIFile->dwCurPos += dwSize;
  1044. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
  1045. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  1046. //
  1047. // Check if glyph data is already in new file
  1048. //
  1049. gdPos = 0;
  1050. for (j=0; j<pFIFile->nGlyphs; j++)
  1051. {
  1052. if (pFIFile->pGlyphData[j].sGlyphID == pFIFile->pFontDir[dwIndex].sGlyphID)
  1053. {
  1054. gdPos = pFIFile->pGlyphData[j].gdPos;
  1055. break;
  1056. }
  1057. }
  1058. if (gdPos == 0)
  1059. {
  1060. HRSRC hrsrc;
  1061. //
  1062. // Get resource from our file
  1063. //
  1064. if (pFIFile->pFontDir[dwIndex].sGlyphID > 0)
  1065. {
  1066. hrsrc = FindResource(ghInstance, MAKEINTRESOURCE(pFIFile->pFontDir[dwIndex].sGlyphID), (LPWSTR)RC_TRANSTAB);
  1067. if (!hrsrc)
  1068. {
  1069. WARNING(("Unable to find RLE resource %d in unidrvui\n", pFIFile->pFontDir[dwIndex].sGlyphID));
  1070. return FALSE;
  1071. }
  1072. pData = (PDATA_HEADER)LockResource(LoadResource(ghInstance, hrsrc));
  1073. }
  1074. else
  1075. pData = NULL;
  1076. if (pData)
  1077. {
  1078. DATA_HEADER dh;
  1079. dh.dwSignature = DATA_CTT_SIG;
  1080. dh.wSize = (WORD)sizeof(DATA_HEADER);
  1081. dh.wDataID = (WORD)pFIFile->pFontDir[dwIndex].sGlyphID;
  1082. dh.dwDataSize = SizeofResource(ghInstance, hrsrc);
  1083. dh.dwReserved = 0;
  1084. pFIFile->pFontDir[dwIndex].offGlyphData = pFIFile->dwCurPos;
  1085. if (!WriteFile(pFIFile->hFile, (PVOID)&dh, sizeof(DATA_HEADER), &dwSize, NULL) ||
  1086. !WriteFile(pFIFile->hFile, (PVOID)pData, dh.dwDataSize, &dwSize, NULL))
  1087. {
  1088. WARNING(("Error writing glyph data to font file\n"));
  1089. return FALSE;
  1090. }
  1091. //
  1092. // Add to set of glyph data's that have been added to file
  1093. //
  1094. pFIFile->pGlyphData[pFIFile->nGlyphs].sGlyphID = pFIFile->pFontDir[dwIndex].sGlyphID;
  1095. pFIFile->pGlyphData[pFIFile->nGlyphs].gdPos = pFIFile->dwCurPos;
  1096. pFIFile->nGlyphs++;
  1097. //
  1098. // Increment number of glyph sets written
  1099. //
  1100. pFIFile->pFileHdr->nGlyphSets++;
  1101. //
  1102. // Update file position
  1103. //
  1104. pFIFile->dwCurPos += sizeof(DATA_HEADER) + dwSize;
  1105. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
  1106. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  1107. }
  1108. else
  1109. {
  1110. pFIFile->pFontDir[dwIndex].offGlyphData = 0;
  1111. }
  1112. }
  1113. else
  1114. {
  1115. //
  1116. // Already in file, just update location
  1117. //
  1118. pFIFile->pFontDir[dwIndex].offGlyphData = gdPos;
  1119. }
  1120. //
  1121. // Write var data
  1122. //
  1123. pFIFile->pFontDir[dwIndex].offVarData = pFIFile->dwCurPos;
  1124. if (!pFntDat->pVarData)
  1125. {
  1126. dwSize = FIWriteVar(pFIFile->hFile, pFntDat->wchFileName);
  1127. }
  1128. else
  1129. {
  1130. dwSize = FIWriteRawVar(pFIFile->hFile, pFntDat->pVarData, pFntDat->dwSize);
  1131. }
  1132. if (dwSize == 0)
  1133. {
  1134. WARNING(("Error writing variable part of font data\n"));
  1135. return FALSE;
  1136. }
  1137. pFIFile->dwCurPos += dwSize;
  1138. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
  1139. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  1140. return TRUE;
  1141. }
  1142. /******************************************************************************
  1143. *
  1144. * FIUpdateFontFile
  1145. *
  1146. * Function:
  1147. * This function closes both files, and if bReplace, it deletes the current
  1148. * file,and sets the new file as the current font installer file in the
  1149. * registry. In !bReplace, it closes both files and deletes the new file.
  1150. *
  1151. * Arguments:
  1152. * hCurFile - Handle identifying current font file
  1153. * hNewFile - Handle identifying new font file
  1154. * bReplace - Whether the new file should replace the current file
  1155. *
  1156. * Returns:
  1157. * TRUE if successful, FALSE otherwise
  1158. *
  1159. ******************************************************************************/
  1160. BOOL
  1161. FIUpdateFontFile(
  1162. HANDLE hCurFile,
  1163. HANDLE hNewFile,
  1164. BOOL bReplace
  1165. )
  1166. {
  1167. FI_FILE *pFICurFile = (FI_FILE*)hCurFile;
  1168. FI_FILE *pFINewFile = (FI_FILE*)hNewFile;
  1169. WCHAR wchCurFileName[MAX_PATH];
  1170. WCHAR wchNewFileName[MAX_PATH];
  1171. HANDLE hPrinter;
  1172. DWORD dwSize;
  1173. //
  1174. // Validate pFINewFile
  1175. // Validate pFINewFile->wchFileName is valid.
  1176. // Validate pFINewFile->hPrinter is valid as well.
  1177. //
  1178. // IsValidFontInfo checks if pFI is not NULL and the signature is valid.
  1179. //
  1180. // pFICurFile could be NULL. In this case this is the first time to install soft fonts.
  1181. //
  1182. if ((pFICurFile && !IsValidFontInfo(pFICurFile)) ||
  1183. (pFINewFile && !IsValidFontInfo(pFINewFile)))
  1184. {
  1185. return FALSE;
  1186. }
  1187. //
  1188. // Initialize local variables
  1189. //
  1190. wchCurFileName[0] = '\0';
  1191. wchNewFileName[0] = '\0';
  1192. //
  1193. // Remember name of the current & new files. We check for non-NULL value
  1194. // because
  1195. // this function can be called in a failure situation with bReplace set
  1196. // to FALSE, and we need to handle all possible faillure cases.
  1197. // If bReplace is TRUE, pFINewFile must be non NULL, so we get hPrinter
  1198. // there
  1199. //
  1200. if (pFINewFile)
  1201. {
  1202. StringCchCopyW(wchNewFileName, CCHOF(wchNewFileName), pFINewFile->wchFileName);
  1203. hPrinter = pFINewFile->hPrinter;
  1204. }
  1205. else
  1206. {
  1207. hPrinter = NULL;
  1208. }
  1209. if (pFICurFile)
  1210. {
  1211. StringCchCopyW(wchCurFileName, CCHOF(wchCurFileName), pFICurFile->wchFileName);
  1212. }
  1213. //
  1214. // Close both files
  1215. //
  1216. FICloseFontFile(hCurFile);
  1217. FICloseFontFile(hNewFile);
  1218. if (bReplace)
  1219. {
  1220. //
  1221. // Copy new file to current file
  1222. //
  1223. if (wchCurFileName[0])
  1224. {
  1225. if (CopyFile(wchNewFileName, wchCurFileName, FALSE))
  1226. {
  1227. //
  1228. // Set printer data so client side caches get updated
  1229. //
  1230. dwSize = (lstrlen(wchCurFileName) + 1) * sizeof(TCHAR);
  1231. if (hPrinter)
  1232. {
  1233. SetPrinterData(hPrinter, REGVAL_FONTFILENAME, REG_SZ, (PBYTE)wchCurFileName, dwSize);
  1234. }
  1235. }
  1236. }
  1237. else
  1238. {
  1239. //
  1240. // Set new file as font file and return (do not delete it!)
  1241. //
  1242. dwSize = (lstrlen(wchNewFileName) + 1) * sizeof(TCHAR);
  1243. if (hPrinter)
  1244. {
  1245. SetPrinterData(hPrinter, REGVAL_FONTFILENAME, REG_SZ, (PBYTE)wchNewFileName, dwSize);
  1246. }
  1247. return TRUE;
  1248. }
  1249. }
  1250. //
  1251. // Delete the new file
  1252. //
  1253. if (wchNewFileName[0])
  1254. {
  1255. DeleteFile(wchNewFileName);
  1256. }
  1257. return TRUE;
  1258. }
  1259. /******************************************************************************
  1260. * Internal helper functions
  1261. ******************************************************************************/
  1262. BOOL
  1263. WriteData(
  1264. PFI_FILE pFIFile,
  1265. PDATA_HEADER pData
  1266. )
  1267. {
  1268. DWORD dwSize;
  1269. if (!WriteFile(pFIFile->hFile, (PVOID)pData, (DWORD)(pData->wSize + pData->dwDataSize), &dwSize, NULL))
  1270. return FALSE;
  1271. pFIFile->dwCurPos += dwSize;
  1272. pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
  1273. pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
  1274. return TRUE;
  1275. }
  1276. /******************************************************************************
  1277. *
  1278. * Qsort
  1279. *
  1280. * Function:
  1281. * This function sorts the given font directory array based on the
  1282. * wFontID field. It used quick sort.
  1283. *
  1284. * Arguments:
  1285. * lpData - Pointer to the font directory array to sort
  1286. * start - Starting index of array
  1287. * end - Ending index of array
  1288. *
  1289. * Returns:
  1290. * Nothing
  1291. *
  1292. ******************************************************************************/
  1293. void
  1294. Qsort(
  1295. PUFF_FONTDIRECTORY lpData,
  1296. int start,
  1297. int end
  1298. )
  1299. {
  1300. int i, j;
  1301. if (start < end) {
  1302. i = start;
  1303. j = end + 1;
  1304. while (1) {
  1305. while (i < j) {
  1306. i++;
  1307. if (lpData[i].wFontID >= lpData[start].wFontID)
  1308. break;
  1309. }
  1310. while(1) {
  1311. j--;
  1312. if (lpData[j].wFontID <= lpData[start].wFontID)
  1313. break;
  1314. }
  1315. if (i < j)
  1316. Exchange(lpData, i, j);
  1317. else
  1318. break;
  1319. }
  1320. Exchange(lpData, start, j);
  1321. Qsort(lpData, start, j-1);
  1322. Qsort(lpData, j+1, end);
  1323. }
  1324. }
  1325. /******************************************************************************
  1326. *
  1327. * Exchange
  1328. *
  1329. * Function:
  1330. * This function exchanges two entries in the font directory array
  1331. *
  1332. * Arguments:
  1333. * lpData - Pointer to the font directory array
  1334. * i, j - Indices of the two entries to exchange
  1335. *
  1336. * Returns:
  1337. * Nothing
  1338. *
  1339. ******************************************************************************/
  1340. void
  1341. Exchange(
  1342. PUFF_FONTDIRECTORY lpData,
  1343. DWORD i,
  1344. DWORD j
  1345. )
  1346. {
  1347. UFF_FONTDIRECTORY fd;
  1348. if ( i != j) {
  1349. memcpy((LPSTR)&fd, (LPSTR)&lpData[i], sizeof(UFF_FONTDIRECTORY));
  1350. memcpy((LPSTR)&lpData[i], (LPSTR)&lpData[j], sizeof(UFF_FONTDIRECTORY));
  1351. memcpy((LPSTR)&lpData[j], (LPSTR)&fd, sizeof(UFF_FONTDIRECTORY));
  1352. }
  1353. }
  1354. #endif // #ifndef KERNEL_MODE