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.

2372 lines
69 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mapfile2.c
  3. *
  4. * Copyright (c) 1997-1999 Microsoft Corporation
  5. \**************************************************************************/
  6. #include "precomp.hxx"
  7. #ifdef _HYDRA_
  8. #include "muclean.hxx"
  9. #endif
  10. extern BOOL G_fConsole;
  11. extern PW32PROCESS gpidSpool;
  12. typedef enum _MAP_MODE {
  13. ModeKernel,
  14. ModeFD
  15. } MAP_MODE;
  16. typedef enum _FONT_IMAGE_TYPE {
  17. RemoteImage = 1,
  18. MemoryImage = 2
  19. } FONT_IMAGE_TYPE;
  20. BOOL bCreateSection(IN PWSTR, OUT FILEVIEW*, IN INT, BOOL *pbIsFAT);
  21. VOID vUnmapFileFD(FILEVIEW*);
  22. BOOL bMapRoutine(FONTFILEVIEW *pffv, FILEVIEW *pfv, MAP_MODE Mode, BOOL bIsFAT);
  23. extern "C" HFASTMUTEX ghfmMemory;
  24. #define SZDLHEADER ALIGN8(offsetof(DOWNLOADFONTHEADER, FileOffsets[1]))
  25. /******************************Public*Routine******************************\
  26. *
  27. * Routine Name:
  28. *
  29. * cMapRemoteFonts
  30. *
  31. * This procedure creates a virtual memory section in which we store
  32. * a copy of the spooler's data buffer. I shall refer to this copy
  33. * as the "spooler section". The pointer to the associated section
  34. * object is saved for later use. A view of the spooler section is
  35. * mapped into the user-mode address space of the calling procedure
  36. * (the spooler process). All the information about the spooler
  37. * section and its mappings is stored in a FONTFILEVIEW
  38. * strucutue supplied by the caller.
  39. *
  40. * Parameters:
  41. *
  42. * ppHeader - address of a variable that gives and receives a
  43. * pointer to a DOWNLOADFONTHEADER structure.
  44. * Upon entry, this is a pointer to a view of the spooler
  45. * section that is valid in the context of the calling
  46. * process (the spooler process).
  47. *
  48. * Upon error the value placed at this address is zero.
  49. *
  50. * cjBuffer - a 32 bit variable that contains the size of the
  51. * spooler image. In the case of MemoryImage fonts
  52. * this size is actually larger than the size of the buffer
  53. * by SZDLHEADER bytes.
  54. *
  55. * pFontFileView - a pointer to a FONTFILEVIEW structure that
  56. * points to incomming receive the information about
  57. * the copy of the spooler image.
  58. *
  59. * Upon error this structure consists of all zero's.
  60. *
  61. * Upon a successful completion of this procedure,
  62. * pFontFileView->gtfv.pvView will point to the first
  63. * font in the spooler buffer and
  64. * pFontFileView->gtfv.cjView will be equal to the
  65. * size of the spooler buffer starting at pvView.
  66. * That is, cjView is equal to cjBuffer minus
  67. * the size of the spooler header.
  68. *
  69. * The fields of the FONTFILEVIEW structure that are
  70. * affected are:
  71. *
  72. * SpoolerBase - points to the base of a view of the spooler
  73. * view of the spooler section. pHeader is
  74. * valid only in the context of the this process
  75. * (the spooler process)
  76. *
  77. * fv.pvView - points to the first font file in the spooler
  78. * view of the spooler section. This view of
  79. * the spooler section is valid only in the
  80. * context of the calling process.
  81. *
  82. * fv.cjView - a 32-bit varaible that contains the size of
  83. * header information is subtracted off. Another
  84. * way to say this is: cjView is the offset of
  85. * the end of the spooler section from the start
  86. * of the image of the first font file.
  87. *
  88. * ulRegionSize - equal to the entire size of the spooler
  89. * section including the header information.
  90. *
  91. * fv.pSection - pointer to the section object controling the
  92. * spooler section. This is a kernel mode
  93. * address and thus is accessable by any process
  94. * in kernel mode.
  95. *
  96. * SpoolerPid - the process id of the calling process. This is
  97. * the id of the process that has valid access
  98. * to pHeader, and fv.pvView.
  99. *
  100. * ImageType - One of RemoteImage or MemoryImage. In
  101. * the case of a remote font image, the image starts
  102. * with a variable length DOWNLOADFONTHEADER structure
  103. * followed by a series of file images at offsets
  104. * specified in the header. In this case cjBuffer is
  105. * equal to the size of the spooler image in bytes. This
  106. * includes the size of the header, the files, and all
  107. * necessary padding. In the case of a memory font image,
  108. * the image is of a single font file; no header, no
  109. * padding. In this case cjBuffer is equal to the size
  110. * of the image plus SZDLHEADER. Here cjBuffer is equal
  111. * to the size of the section to be produced which will
  112. * start with a header, generated here, followed by
  113. * a single font file image.
  114. *
  115. * Called by:
  116. *
  117. * NtGdiAddRemoteFontToDC
  118. *
  119. \**************************************************************************/
  120. extern "C" ULONG cMapRemoteFonts(
  121. DOWNLOADFONTHEADER **ppHeader, // IN OUT pointer to spooler buffer
  122. // mapped into CSRSS address sapce
  123. COUNT cjBuffer, // IN size of spooler buffer in bytes
  124. FONTFILEVIEW *pFontFileView, // OUT pointer to mapped file information
  125. FONT_IMAGE_TYPE ImageType // {Remote, Memory}
  126. )
  127. {
  128. NTSTATUS NtStatus;
  129. PVOID pSection, pView;
  130. LARGE_INTEGER MaximumSize;
  131. LARGE_INTEGER SectionOffset;
  132. SIZE_T ViewSize;
  133. ULONG TempSize, NumFiles;
  134. BOOL bRet;
  135. BOOL bSpooledType1 = FALSE;
  136. DOWNLOADFONTHEADER *pHeader, *pCopy;
  137. // Copy the address of the spooler data into pHeader for safe keeping
  138. pHeader = *ppHeader;
  139. // Set the (return value) of the address of the copy of the spooler
  140. // data to zero. This indicates error.
  141. *ppHeader = 0;
  142. #define MAX_FONTFILE 0x10000000
  143. // claudebe 6/24/99, the new surrogate enabled MungLui is blowing the previous limit of 0x80000000
  144. ASSERTGDI(cjBuffer <= MAX_FONTFILE, "cjBuffer > MAX_FONTFILE");
  145. // return 0 if cjBuffer is bogus
  146. if ((cjBuffer > MAX_FONTFILE) || (cjBuffer < sizeof(DOWNLOADFONTHEADER)))
  147. {
  148. return 0;
  149. }
  150. // Initialize these variables to zero to prevent unintended access
  151. // in the clean up code at the end of this routine. We also zero
  152. // out the FONTFILEVIEW structure, not only to indicate error, but
  153. // this will save us explicitly zeroing fields that we do not touch
  154. // in this routine.
  155. pSection = 0;
  156. pView = 0;
  157. if (pFontFileView == 0)
  158. {
  159. return(0);
  160. }
  161. RtlZeroMemory(pFontFileView, sizeof(*pFontFileView));
  162. if (ImageType == RemoteImage)
  163. {
  164. __try
  165. {
  166. ProbeForRead(pHeader, sizeof(DOWNLOADFONTHEADER), sizeof(ULONG));
  167. NumFiles = pHeader->NumFiles;
  168. }
  169. __except(EXCEPTION_EXECUTE_HANDLER)
  170. {
  171. WARNING("cMapRemoteFonts: invalid pointer pHeader\n");
  172. return (0);
  173. }
  174. // do some checks to ensure that these numbers are not entirely bogus.
  175. // Eg. in reality we never have more than 3 files per font, the total
  176. // sum of their sizes should not exceed MAX_FONTFILE (32MB for now);
  177. // ClaudeBe 6/24/99, limit extended to 256 MB
  178. ASSERTGDI(NumFiles <= 3, "NumFiles not reasonable\n");
  179. if (NumFiles > 3)
  180. {
  181. return 0;
  182. }
  183. // The upper limit on the size of the spooler section is 256Mb
  184. if (0x10000000 < cjBuffer)
  185. {
  186. return(0);
  187. }
  188. if (!IS_USER_ADDRESS(pHeader))
  189. {
  190. return(0);
  191. }
  192. // If this a pfm,pfb image spooled from the NT 4.0 client,
  193. // NumFiles will be set to zero and Type1ID will be set to
  194. // ufi hash value. In this case we have to set the NumFiles to 2:
  195. if (NumFiles == 0)
  196. {
  197. bSpooledType1 = TRUE;
  198. NumFiles = 2;
  199. }
  200. }
  201. else
  202. {
  203. // for MemoryImage, NumFiles should be 1
  204. NumFiles = 1;
  205. }
  206. // Set TempSize to be equal to the size of the stuff preceeding
  207. // the first font file. This is the size of the header information
  208. // if you wish
  209. TempSize = ALIGN8(offsetof(DOWNLOADFONTHEADER, FileOffsets[NumFiles]));
  210. // return 0 if the TempSize is bigger than cjBuffer
  211. if (cjBuffer < TempSize)
  212. {
  213. return 0;
  214. }
  215. // Create a section where we will store a copy of the spooler data
  216. MaximumSize.QuadPart = (LONGLONG) cjBuffer;
  217. NtStatus =
  218. Win32CreateSection(
  219. &pSection , // SectionObject
  220. SECTION_ALL_ACCESS , // DesiredAccess
  221. 0 , // ObjectAttributes
  222. &MaximumSize , // MaximumSize
  223. PAGE_READWRITE , // SectionPageProtection
  224. SEC_COMMIT , // AllocationAttributes
  225. 0 , // FileHandle
  226. 0 , // FileObject
  227. TAG_SECTION_REMOTEFONT
  228. );
  229. if (!NT_SUCCESS(NtStatus))
  230. {
  231. return(0);
  232. }
  233. // Map a view of the spooler section into the user mode address space
  234. // of the current process (this spooler process)
  235. SectionOffset.QuadPart = 0;
  236. ViewSize = cjBuffer;
  237. ASSERTGDI(pView == 0, "pView != 0\n");
  238. // Temporarily map a view of the section into the user mode address space
  239. // of the spooler process. This will allow us to copy the data from
  240. // the spool file to the section. After we are done we will close
  241. // this mapping and open a mapping into the user mode address space
  242. // of the CSRSS process.
  243. NtStatus =
  244. MmMapViewOfSection(
  245. pSection , // SectionToMap,
  246. PsGetCurrentProcess(), // spooler process
  247. &pView , // CapturedBase,
  248. 0 , // ZeroBits,
  249. ViewSize , // CommitSize,
  250. &SectionOffset , // SectionOffset,
  251. &ViewSize , // CapturedViewSize,
  252. ViewUnmap , // InheritDisposition,
  253. SEC_NO_CHANGE , // AllocationType,
  254. PAGE_READWRITE // Allow writing on this view
  255. );
  256. if (!NT_SUCCESS(NtStatus))
  257. {
  258. Win32DestroySection(pSection);
  259. return(0);
  260. }
  261. // this operation is a suspect for copying into 0-th page of csrss:
  262. ASSERTGDI(pView, "pView == 0\n");
  263. // Change pHeader to point at the copy
  264. DOWNLOADFONTHEADER *pTmp = pCopy = (DOWNLOADFONTHEADER*) pView;
  265. if (ImageType == MemoryImage)
  266. {
  267. // pHeader is a buffer of size cjBuffer - SZDLHEADER
  268. // advance the pointer to the right position
  269. cjBuffer -= SZDLHEADER;
  270. pView = (PBYTE)pView + SZDLHEADER;
  271. // fill out the fields in DOWNLOADFONTHEADER for memory fonts
  272. __try
  273. {
  274. ProbeAndWriteUlong( &pTmp->Type1ID, 0);
  275. ProbeAndWriteUlong( &pTmp->NumFiles, NumFiles);
  276. ProbeAndWriteUlong( &pTmp->FileOffsets[0], cjBuffer);
  277. bRet = TRUE;
  278. }
  279. __except(EXCEPTION_EXECUTE_HANDLER)
  280. {
  281. WARNING("cMapRemoteFonts: exception occured for memory image\n");
  282. EngSetLastError(ERROR_INVALID_PARAMETER);
  283. bRet = FALSE;
  284. }
  285. if (bRet == FALSE)
  286. {
  287. NtStatus = MmUnmapViewOfSection(PsGetCurrentProcess(), (PVOID)pCopy);
  288. if (!NT_SUCCESS(NtStatus))
  289. {
  290. WARNING("Could not unmap the current process view of the memory font\n");
  291. }
  292. Win32DestroySection(pSection);
  293. return(0);
  294. }
  295. }
  296. // Copy the spooler data into this view of the spooler section
  297. __try
  298. {
  299. ProbeForRead(pHeader, cjBuffer, sizeof(BYTE));
  300. RtlCopyMemory(pView, pHeader, cjBuffer);
  301. bRet = TRUE;
  302. }
  303. __except(EXCEPTION_EXECUTE_HANDLER)
  304. {
  305. WARNING("cMapRemoteFonts: exception occured\n");
  306. EngSetLastError(ERROR_INVALID_PARAMETER);
  307. bRet = FALSE;
  308. }
  309. // fix the spooled (from NT 4.0) Type1 font case:
  310. if (bSpooledType1)
  311. {
  312. __try
  313. {
  314. ProbeAndWriteUlong( &pTmp->Type1ID, 0);
  315. ProbeAndWriteUlong( &pTmp->NumFiles, NumFiles);
  316. }
  317. __except(EXCEPTION_EXECUTE_HANDLER)
  318. {
  319. WARNING("cMapRemoteFonts: exception occured\n");
  320. EngSetLastError(ERROR_INVALID_PARAMETER);
  321. bRet = FALSE;
  322. }
  323. }
  324. // We have OR have not successfully completed copying the data
  325. // from the file to the section. In either case we no longer
  326. // need this view of the section
  327. // so we will unmap the spooler view at this time
  328. NtStatus = MmUnmapViewOfSection(PsGetCurrentProcess(), (PVOID)pCopy);
  329. if (!NT_SUCCESS(NtStatus))
  330. {
  331. WARNING("Could not unmap the current process view of the memory font\n");
  332. KdPrint(("Could not unmap the current process view of the memory font\n"));
  333. Win32DestroySection(pSection);
  334. return(0);
  335. }
  336. if (bRet == FALSE)
  337. {
  338. Win32DestroySection(pSection);
  339. return(0);
  340. }
  341. // Now we will map a view into the user mode address space
  342. // of the CSRSS process. Remember that this view cannot
  343. // be seen by the current process.
  344. pView = 0;
  345. ViewSize = 0;
  346. SectionOffset.QuadPart = 0;
  347. NtStatus =
  348. MmMapViewOfSection(
  349. pSection , // SectionToMap,
  350. gpepCSRSS , // CSRSS process
  351. &pView , // CapturedBase,
  352. 0 , // ZeroBits,
  353. ViewSize , // CommitSize,
  354. &SectionOffset , // SectionOffset,
  355. &ViewSize , // CapturedViewSize,
  356. ViewUnmap , // InheritDisposition,
  357. SEC_NO_CHANGE , // AllocationType,
  358. PAGE_READONLY // No writing on this view
  359. );
  360. if (!NT_SUCCESS(NtStatus))
  361. {
  362. Win32DestroySection(pSection);
  363. return(0);
  364. }
  365. ASSERTGDI((ULONG_PTR)pView > 0x100000,
  366. "cmap remote fonts: csrss view smaller than 1MB \n");
  367. // Reset pCopy to point to a view of the section in the context
  368. // of the CSRSS process. CAUTION - you cannot access any data
  369. // off of pCopy or pView after this point.
  370. pCopy = (DOWNLOADFONTHEADER*) pView;
  371. if (ImageType == MemoryImage)
  372. {
  373. // reset the size and pointer
  374. cjBuffer += SZDLHEADER;
  375. pView = pCopy;
  376. }
  377. // Set the FONTFILEVIEW
  378. //
  379. // SpoolerBase points at the base of the copy.
  380. // pvView points to the first font image.
  381. // cjView is the size of the section with starting
  382. // at the first font image.
  383. // ulRegionSize is set to the size of the entire view.
  384. pFontFileView->SpoolerBase = pCopy;
  385. pFontFileView->fv.pvViewFD = (char*) pCopy + TempSize;
  386. pFontFileView->fv.cjView = cjBuffer - TempSize;
  387. pFontFileView->ulRegionSize = ViewSize;
  388. // We have to set FD ref count to 1, KM ref count to zero [bodind]
  389. pFontFileView->cKRefCount = 0;
  390. pFontFileView->cRefCountFD = 1;
  391. pFontFileView->fv.pSection = pSection;
  392. pFontFileView->SpoolerPid = W32GetCurrentPID(); // this could be the pid of the spooler
  393. // or the pid of the current process which is loading a memory font
  394. *ppHeader = pCopy; // Valid in CSRSS process only.
  395. return(NumFiles);
  396. }
  397. /******************************Public*Routine******************************\
  398. *
  399. * vUnmapRemoteFonts
  400. *
  401. * This is a remote font so delete the memory for the view.
  402. *
  403. * CAUTION
  404. *
  405. * This code is intimately linked with NtGdiAddRemoteFontToDC()
  406. * so any changes here should be synchronized there.
  407. *
  408. * The pool memory starts with a DOWNLOADFONTHEADER followed by the
  409. * file image pointed to by pvView. We must pass the pointer to the
  410. * beginning of the pool allocation to the free routine.
  411. *
  412. *
  413. * Spooler data format for Engine fonts
  414. *
  415. *
  416. * DOWNLOADFONTHEADER PADDING
  417. * | |
  418. * | |- FILE OFFSETS-| |
  419. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  420. * | 0 | 1 | 2 | 3 | N | x | font image #0 | font image #1 |...
  421. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  422. * ^
  423. * pvView points to first font image
  424. *
  425. *
  426. * Parameters:
  427. *
  428. * pFontFileView - a 32-bit variable that contains a pointer to a
  429. * FONTFILEVIEW structure that describes the very
  430. * first font file image in the spooler data.
  431. *
  432. * Return Value:
  433. *
  434. * none
  435. *
  436. * Called by:
  437. *
  438. * NtGdiAddRemoteFontsToDC
  439. * FreeFileView
  440. *
  441. \**************************************************************************/
  442. extern "C" void vUnmapRemoteFonts(FONTFILEVIEW *pFontFileView)
  443. {
  444. if (pFontFileView == 0)
  445. {
  446. return;
  447. }
  448. ASSERTGDI(pFontFileView->SpoolerPid == W32GetCurrentPID() ||
  449. gpidSpool == (PW32PROCESS)W32GetCurrentProcess(),
  450. "vUnmapRemoteFonts: wrong process freeing remote font data\n");
  451. // We initialize the cRefCountFD to 1 in cMapRemoteFonts() function
  452. if (pFontFileView->cRefCountFD)
  453. {
  454. pFontFileView->cRefCountFD -= 1;
  455. }
  456. if (pFontFileView->cRefCountFD == 0)
  457. {
  458. if (pFontFileView->fv.pSection)
  459. {
  460. if (pFontFileView->SpoolerBase)
  461. {
  462. MmUnmapViewOfSection(gpepCSRSS, pFontFileView->SpoolerBase);
  463. pFontFileView->SpoolerBase = NULL;
  464. }
  465. Win32DestroySection(pFontFileView->fv.pSection);
  466. pFontFileView->fv.pSection = 0;
  467. }
  468. }
  469. }
  470. /******************************Public*Routine******************************\
  471. *
  472. * bCreateFontFileView
  473. *
  474. \**************************************************************************/
  475. BOOL bCreateFontFileView(
  476. FONTFILEVIEW *pFontFileViewIn, // kernel mode address
  477. DOWNLOADFONTHEADER *pHeader, // CSRSS address of spool section
  478. COUNT cjBuffer,
  479. FONTFILEVIEW ***papfv,
  480. ULONG NumFiles
  481. )
  482. {
  483. FONTFILEVIEW **apfv, *pFontFileView, FontFileView;
  484. NTSTATUS NtStatus;
  485. ULONG offset;
  486. COUNT cjHeader;
  487. BOOL bRet = TRUE;
  488. //
  489. // In order to see the data pointed to by pHeader we must attach
  490. // to the address space of the CSRSS process
  491. //
  492. KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
  493. //
  494. // engine fonts
  495. //
  496. apfv = 0;
  497. FontFileView = *pFontFileViewIn;
  498. cjHeader = ALIGN8(offsetof(DOWNLOADFONTHEADER,FileOffsets[NumFiles]));
  499. if (cjBuffer <= cjHeader)
  500. {
  501. EngSetLastError(ERROR_INVALID_PARAMETER);
  502. KeDetachProcess();
  503. return FALSE;
  504. }
  505. //
  506. // The lowest part of the block of memory pointed to by apfv
  507. // will be occupied by NumFiles pointers to FONTFILEVIEW structures.
  508. // The FONTFILEVIEW structures pointed to by these pointers follow
  509. // at the first 8-byte aligned address after the array of pointers.
  510. //
  511. /*********************************************************************************
  512. * *
  513. * Structure of data pointed to by `apfv' *
  514. * *
  515. * pointer data +----------------------------+ *
  516. * | V *
  517. * +---+ +---+---+---+---+---+---+----+---+---+---+----+---+---+---+----+---+ *
  518. * |apfv ... | p | p | p | |FONTFILEVIEW| |FONTFILEVIEW| |FONTFILEVIEW| | *
  519. * +---+ +---+---+---+---+---+---+----+---+---+---+----+---+---+---+----+---+ *
  520. * | ^ | ^ *
  521. * +-------+ +-------------+ *
  522. * *
  523. * | | *
  524. * |<-- offset --->| *
  525. * *
  526. *********************************************************************************/
  527. //
  528. // `offset' is the count of bytes from the beginning of the allocated
  529. // memory to where the array of FONTFILEVIEW structures starts. An array
  530. // of FONTFILEVIEW pointers preceeds.
  531. //
  532. offset = ALIGN8(sizeof(FONTFILEVIEW*) * NumFiles);
  533. apfv = (FONTFILEVIEW**) PALLOCMEM(sizeof(FONTFILEVIEW) * NumFiles + offset, 'vffG');
  534. if (apfv == 0)
  535. {
  536. EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  537. KeDetachProcess();
  538. return FALSE;
  539. }
  540. //
  541. // Only initiaze these values for one file view in the
  542. // array. This file view will be used to free the entire
  543. // block of memory containing all the files.
  544. //
  545. FONTFILEVIEW **ppFontFileView = apfv;
  546. pFontFileView = (FONTFILEVIEW*) ((char*) apfv + offset);
  547. //
  548. // FileOffset[i] = offset of File[i+1] from begining of first
  549. // font file view
  550. //
  551. // Size[i] = FileOffset[i] - FileOffset[i-1];
  552. //
  553. //
  554. // copy the FONTFILEVIEW structure initialized by vMapSpoolerFontFiles
  555. // into the first positon in the array
  556. //
  557. *pFontFileView = FontFileView;
  558. //
  559. // Set pchView to point to the first FONTFILEVIEW structure in the
  560. // array
  561. //
  562. char *pchView = (char*) FontFileView.fv.pvViewFD;
  563. //
  564. // pchLast points to illegal memory. This step relies on
  565. // vMapRemotFonts to place in cjView the size of the view as
  566. // though it were based at the start of the first file.
  567. //
  568. char *pchLast = pchView + FontFileView.fv.cjView;
  569. ULONG Offset = 0;
  570. ULONG *pOffset = &(pHeader->FileOffsets[0]);
  571. ULONG *pOffsetLast = pOffset + NumFiles;
  572. for (; pOffset < pOffsetLast; pOffset++)
  573. {
  574. ULONG NextOffset = *pOffset;
  575. ULONG cjView = NextOffset - Offset;
  576. Offset = ALIGN4(NextOffset);
  577. // the offset alignement must correspond to \ntgdi\client\ufi.c WriteFontToSpoolFile()
  578. // if there is a need for different alignement, then we would need to map each file separately
  579. ASSERTGDI(Offset == NextOffset, "bCreateFontFileView ALIGN difference between client and server");
  580. if (pchLast < pchView + cjView)
  581. {
  582. bRet = FALSE;
  583. break;
  584. }
  585. pFontFileView->fv.pvViewFD = pchView;
  586. pFontFileView->fv.cjView = cjView;
  587. //
  588. // move pchView to point at the next font image
  589. //
  590. pchView += cjView;
  591. *ppFontFileView = pFontFileView;
  592. ppFontFileView++;
  593. pFontFileView++;
  594. }
  595. if (!bRet)
  596. {
  597. VFREEMEM(apfv);
  598. }
  599. else
  600. {
  601. *papfv = apfv;
  602. }
  603. KeDetachProcess();
  604. return (bRet);
  605. }
  606. /******************************Public*Routine******************************\
  607. *
  608. * NtGdiAddRemoteFontToDC
  609. *
  610. * This routine is called by the spooler process, at playback time, to
  611. * add remote fonts to a printer DC. The font files in question are for
  612. * the use of the associated print job only. No other application can
  613. * have access. In order to prevent mischevious application on the server
  614. * from picking up font to which it has not right, we have chosen to not
  615. * copy the file images contained in the spool file to separate font file
  616. * on the disk. This means that the spooler process cannot use
  617. * AddFontResource to allow the DC access to the fonts.
  618. * Instead, we have introduced this private entry point for the spooler.
  619. *
  620. * Parameters:
  621. *
  622. * hdc - handle to DC to which remote font is to be added
  623. *
  624. * pvBuffer - pointer to a DOWNLOADFONTHEADER that details
  625. * the location of the font files contained
  626. * withing this buffer.
  627. *
  628. * cjBuffer - is the size of the buffe, in bytes, pointed
  629. * to by pvBuffer
  630. *
  631. * Return Value:
  632. *
  633. * TRUE if successful, FALSE if not.
  634. *
  635. * Remarks:
  636. *
  637. * In the process of loading the fonts to the spooler DC, we create
  638. * an array of FONTFILEVIEW structures. The lowest part of the block
  639. * of memory pointed to by apfv will be occupied by NumFiles pointers
  640. * to FONTFILEVIEW structures. The FONTFILEVIEW structures pointed to
  641. * by these pointers follow at the first 8-byte aligned address after
  642. * the array of pointers.
  643. *
  644. * Structure of data pointed to by `apfv'
  645. *
  646. * pointer data +----------------------------+
  647. * | V
  648. * +---+ +---+---+---+---+---+---+----+---+---+---+----+---+---+---+----+---+
  649. * |apfv ... | p | p | p | |FONTFILEVIEW| |FONTFILEVIEW| |FONTFILEVIEW| |
  650. * +---+ +---+---+---+---+---+---+----+---+---+---+----+---+---+---+----+---+
  651. * | ^ | ^
  652. * +-------+ +-------------+
  653. *
  654. * | |
  655. * |<-- offset --->|
  656. *
  657. \**************************************************************************/
  658. extern "C" BOOL APIENTRY NtGdiAddRemoteFontToDC(
  659. HDC hdc , // handle to DC to which remote font is to be added
  660. PVOID pvBuffer , // pointer to spool font file image
  661. COUNT cjBuffer , // size of spool font file image
  662. PUNIVERSAL_FONT_ID pufi //orignal ufi for subsetted font, used for remote printing only
  663. )
  664. {
  665. FONTFILEVIEW FontFileView, **apfv, *pFontFileView;
  666. DOWNLOADFONTHEADER *pHeader;
  667. NTSTATUS NtStatus;
  668. ULONG offset;
  669. ULONG NumFiles;
  670. BOOL bRet;
  671. BOOL bMappedSpoolerFont;
  672. UNIVERSAL_FONT_ID ufiTmp;
  673. UNIVERSAL_FONT_ID *pufiTmp = pufi;
  674. __try
  675. {
  676. if (pufiTmp)
  677. {
  678. ufiTmp = ProbeAndReadStructure(pufiTmp, UNIVERSAL_FONT_ID);
  679. pufiTmp = &ufiTmp;
  680. }
  681. bRet = TRUE;
  682. }
  683. __except(EXCEPTION_EXECUTE_HANDLER)
  684. {
  685. bRet = FALSE;
  686. }
  687. if (!bRet)
  688. return bRet;
  689. bRet = FALSE;
  690. XDCOBJ dco(hdc);
  691. if (!dco.bValid())
  692. {
  693. return bRet;
  694. }
  695. apfv = 0;
  696. pFontFileView = NULL;
  697. pHeader = (DOWNLOADFONTHEADER*) pvBuffer;
  698. NumFiles = cMapRemoteFonts(&pHeader, cjBuffer, &FontFileView, RemoteImage);
  699. if (pHeader == 0)
  700. {
  701. goto exit_point;
  702. }
  703. bRet = TRUE;
  704. pFontFileView = &FontFileView;
  705. if (NumFiles)
  706. {
  707. // engine fonts
  708. if (bRet = bCreateFontFileView(&FontFileView, pHeader, cjBuffer, &apfv, NumFiles))
  709. {
  710. PUBLIC_PFTOBJ pfto;
  711. bRet = pfto.bLoadRemoteFonts(dco, apfv, NumFiles, 0, pufiTmp);
  712. }
  713. }
  714. exit_point:
  715. if (!bRet)
  716. {
  717. if (pFontFileView)
  718. {
  719. vUnmapRemoteFonts(pFontFileView);
  720. }
  721. if (apfv)
  722. {
  723. VFREEMEM(apfv);
  724. }
  725. }
  726. dco.vUnlockFast();
  727. return (bRet);
  728. }
  729. /******************************Public*Routine******************************\
  730. *
  731. * GreAddFontMemResourceEx
  732. *
  733. * This function uses same routines that NtGdiAddRemoteToDC()
  734. * uses to create the file view structrues before it can load
  735. * the font into the system. Memory fonts are always added as
  736. * private to the private font tale.
  737. *
  738. \**************************************************************************/
  739. HANDLE GreAddFontMemResourceEx(
  740. PVOID pvBuffer,
  741. ULONG cjBuffer,
  742. DESIGNVECTOR *pdv,
  743. DWORD cjDV,
  744. DWORD *pNumFonts
  745. )
  746. {
  747. FONTFILEVIEW **apfv, FontFileView;
  748. DOWNLOADFONTHEADER *pHeader;
  749. ULONG NumFiles;
  750. HANDLE hMMFont = 0;
  751. BOOL bOK = FALSE;
  752. apfv = 0;
  753. pHeader = (DOWNLOADFONTHEADER*) pvBuffer;
  754. // in order to use the same routines used by remote fonts, we need to
  755. // attach a DOWNLOADFONTHEADER structure in fron of the font image
  756. cjBuffer += SZDLHEADER;
  757. NumFiles = cMapRemoteFonts(&pHeader, cjBuffer, &FontFileView, MemoryImage);
  758. if (pHeader != 0)
  759. {
  760. ASSERTGDI(NumFiles == 1, "GreAddFontMemResourceEx() NumFiles != 1\n");
  761. if (bCreateFontFileView(&FontFileView, pHeader, cjBuffer, &apfv, 1))
  762. {
  763. if (gpPFTPrivate || bInitPrivatePFT())
  764. {
  765. PUBLIC_PFTOBJ pfto(gpPFTPrivate);
  766. ULONG cFonts;
  767. bOK = TRUE;
  768. // if hLoadMemFonts fail to load a bad font, apfv is already released
  769. // inside hLoadMemFonts at FreeFileView and doesn't need to be freed
  770. // below, see Windows bug 770114
  771. if (hMMFont = pfto.hLoadMemFonts(apfv, pdv, cjDV, &cFonts))
  772. {
  773. *pNumFonts = cFonts;
  774. }
  775. }
  776. }
  777. else
  778. {
  779. vUnmapRemoteFonts(&FontFileView);
  780. }
  781. }
  782. if (!bOK && apfv)
  783. {
  784. VFREEMEM(apfv);
  785. }
  786. return hMMFont;
  787. }
  788. /******************************Public*Routine******************************\
  789. *
  790. * FreeFileView
  791. *
  792. * This routine is called to free the copy of the spooler data,
  793. * if it exists.
  794. *
  795. * Parameters:
  796. *
  797. * apfv - pointer to an array of FONTFILEVIEW pointers.
  798. * The number of pointers in the array is given by cFiles.
  799. *
  800. * cFiles - a 32-bit variable containing the number of pointers in
  801. * the array pointed to by apfv.
  802. *
  803. * Return Value:
  804. *
  805. * None.
  806. *
  807. * Called by:
  808. *
  809. * PFFOBJ::pPFFC_Delete
  810. *
  811. \**************************************************************************/
  812. extern "C" void FreeFileView(PFONTFILEVIEW apfv[], ULONG cFiles)
  813. {
  814. FONTFILEVIEW *pfv, **ppfv;
  815. for (ppfv = apfv; ppfv < apfv + cFiles; ppfv++)
  816. {
  817. pfv = *ppfv;
  818. if (pfv->ulRegionSize)
  819. {
  820. vUnmapRemoteFonts(pfv);
  821. }
  822. }
  823. VFREEMEM(apfv);
  824. }
  825. /******************************Public*Routine******************************\
  826. *
  827. * BOOL EngMapFontFileInternal
  828. *
  829. * This is called by font drivers to return a buffer containing the
  830. * raw bytes for a font file, given a handle passed to DrvLoadFontFile.
  831. * The handle is really a pointer to the PFF for this file.
  832. *
  833. * Parameters:
  834. *
  835. * iFile - Supplies a 32-bit identifier of the font file. This is
  836. * the value supplied in DrvLoadFontFile.
  837. *
  838. * ppjBuf - Supplies a pointer to a variable that will receive the
  839. * address of the base of the view of the file.
  840. *
  841. * pcjBuf - Supplies a pointer to a variable that will receive the
  842. * size of the view of the file.
  843. * bFontDrv - if this is called by font driver.
  844. *
  845. * Return Values:
  846. *
  847. * TRUE if successufl, FALSE if not.
  848. *
  849. * Called by:
  850. *
  851. * PUBLIC_PFTOBJ::bLoadFonts
  852. * NtGdiAddRemoteFontToDC
  853. * GreMakeFontDir
  854. *
  855. * History:
  856. * 20-Jan-1995 -by- Gerrit van Wingerden
  857. *
  858. \**************************************************************************/
  859. BOOL EngMapFontFileInternal(
  860. ULONG_PTR iFile ,
  861. PULONG *ppjBuf,
  862. ULONG *pcjBuf,
  863. BOOL bFontDrv
  864. )
  865. {
  866. PFONTFILEVIEW pffv = (PFONTFILEVIEW) iFile;
  867. BOOL bMapIt,bRet;
  868. FILEVIEW fv;
  869. RtlZeroMemory(&fv, sizeof(fv));
  870. bRet = TRUE;
  871. bMapIt = TRUE;
  872. GreAcquireFastMutex(ghfmMemory);
  873. if (pffv->fv.pvKView)
  874. {
  875. bMapIt = FALSE;
  876. pffv->cKRefCount += 1;
  877. }
  878. else if (!pffv->pwszPath)
  879. {
  880. RIP("fv.pvKView==0 && pwszPath==0\n");
  881. }
  882. else if (pffv->fv.pSection)
  883. {
  884. NTSTATUS NtStatus;
  885. SIZE_T ViewSize;
  886. LARGE_INTEGER SectionOffset;
  887. SectionOffset.QuadPart = 0;
  888. ViewSize = 0;
  889. #if defined(_GDIPLUS_)
  890. NtStatus = MapViewInProcessSpace(
  891. pffv->fv.pSection,
  892. &pffv->fv.pvKView,
  893. &ViewSize);
  894. #elif defined(_HYDRA_)
  895. // MmMapViewInSessionSpace is internally promoted to
  896. // MmMapViewInSystemSpace on non-Hydra systems.
  897. NtStatus= Win32MapViewInSessionSpace(
  898. pffv->fv.pSection,
  899. &pffv->fv.pvKView,
  900. &ViewSize);
  901. #else
  902. NtStatus = MmMapViewInSystemSpace(
  903. pffv->fv.pSection,
  904. &pffv->fv.pvKView,
  905. &ViewSize);
  906. #endif
  907. if (bRet = NT_SUCCESS(NtStatus))
  908. {
  909. #ifdef _HYDRA_
  910. #if DBG
  911. if (!G_fConsole)
  912. {
  913. DebugGreTrackAddMapView(pffv->fv.pvKView);
  914. }
  915. #endif
  916. #endif
  917. pffv->cKRefCount = 1;
  918. }
  919. bMapIt = FALSE;
  920. }
  921. GreReleaseFastMutex(ghfmMemory);
  922. if (bMapIt)
  923. {
  924. BOOL bMapOK, bIsFAT;
  925. // If the call is from the font driver, the current thread
  926. // is attached to the CSRSS process. By attaching it to the
  927. // CSRSS, the thread loses its user security context which
  928. // prevents the thread to open a network font file.
  929. if (bFontDrv)
  930. KeDetachProcess();
  931. bMapOK = bMapFile(pffv->pwszPath, &fv, 0, &bIsFAT);
  932. if (bFontDrv)
  933. KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
  934. if (!bMapOK)
  935. {
  936. bRet = FALSE;
  937. }
  938. else
  939. {
  940. BOOL bKeepIt;
  941. GreAcquireFastMutex(ghfmMemory);
  942. pffv->cKRefCount += 1;
  943. if (pffv->fv.pvKView)
  944. {
  945. bKeepIt = FALSE; // file mapped by another thread
  946. }
  947. else
  948. {
  949. bRet = bKeepIt = bMapRoutine(pffv, &fv, ModeKernel, bIsFAT);
  950. }
  951. GreReleaseFastMutex(ghfmMemory);
  952. if (!bKeepIt)
  953. {
  954. vUnmapFile(&fv);
  955. }
  956. }
  957. }
  958. if (bRet)
  959. {
  960. //
  961. // it's okay to access these without grabbing the MUTEX since we've
  962. // incremented the reference count;
  963. //
  964. if (ppjBuf)
  965. {
  966. *ppjBuf = (ULONG*) pffv->fv.pvKView;
  967. }
  968. if (pcjBuf)
  969. {
  970. *pcjBuf = pffv->fv.cjView;
  971. }
  972. }
  973. return(bRet);
  974. }
  975. /***********************Public*Routine*********************\
  976. *
  977. * BOOL EngMapFontFile
  978. *
  979. * History:
  980. * 20-Jan-1995 -by- Gerrit van Wingerden
  981. *
  982. \**********************************************************/
  983. BOOL EngMapFontFile(
  984. ULONG_PTR iFile ,
  985. PULONG *ppjBuf,
  986. ULONG *pcjBuf
  987. )
  988. {
  989. return (EngMapFontFileInternal(iFile, ppjBuf, pcjBuf, FALSE));
  990. }
  991. /******************************Public*Routine******************************\
  992. *
  993. * EngUnmapFontFile
  994. *
  995. * This is called by font drivers to unmap a file mapped by a previous
  996. * call to EngMapFontFile.
  997. *
  998. * Parameters:
  999. *
  1000. * iFile - is the font identifier as returned by EngMapFontFile.
  1001. *
  1002. * Return Value:
  1003. *
  1004. * None.
  1005. *
  1006. * Called by:
  1007. *
  1008. * PUBLIC_PFTOBJ::bLoadFonts
  1009. * GreMakeFontDir
  1010. *
  1011. \**************************************************************************/
  1012. void EngUnmapFontFile(ULONG_PTR iFile)
  1013. {
  1014. FILEVIEW fv;
  1015. PFONTFILEVIEW pffv = (PFONTFILEVIEW) iFile;
  1016. fv.pvKView = NULL;
  1017. GreAcquireFastMutex(ghfmMemory);
  1018. if (pffv->cKRefCount)
  1019. {
  1020. pffv->cKRefCount -= 1;
  1021. if (pffv->cKRefCount == 0)
  1022. {
  1023. if (pffv->pwszPath)
  1024. {
  1025. fv = pffv->fv; // copy pvKView, pvViewFD and pSection;
  1026. pffv->fv.pvKView = 0;
  1027. if (pffv->fv.pvViewFD == 0)
  1028. {
  1029. pffv->fv.pSection = 0;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. GreReleaseFastMutex(ghfmMemory);
  1035. if (fv.pvKView)
  1036. {
  1037. vUnmapFile(&fv);
  1038. }
  1039. }
  1040. /******************************Public*Routine******************************\
  1041. * BOOL bMapFile
  1042. *
  1043. * Similar to PosMapFile except that it takes unicode file name
  1044. *
  1045. * If iFileSize is -1 then the file is module is mapped for read/write. If
  1046. * iFileSize is > 0 then the file is extended or truncated to be iFileSize
  1047. * bytes in size and is mapped for read/write.
  1048. *
  1049. * History:
  1050. * 21-May-1991 -by- Bodin Dresevic [BodinD]
  1051. * Wrote it.
  1052. \**************************************************************************/
  1053. BOOL bMapFile(PWSTR pwszFileName, FILEVIEW *pfvw, INT iFileSize, BOOL *pbIsFAT)
  1054. {
  1055. FILEVIEW fv;
  1056. NTSTATUS NtStatus;
  1057. BOOL ReturnValue;
  1058. SIZE_T ViewSize;
  1059. ReturnValue = FALSE;
  1060. if (bCreateSection(pwszFileName, &fv, iFileSize, pbIsFAT))
  1061. {
  1062. ViewSize = 0;
  1063. #if defined(_GDIPLUS_)
  1064. NtStatus = MapViewInProcessSpace(fv.pSection, &fv.pvKView, &ViewSize);
  1065. #elif defined(_HYDRA_)
  1066. // MmMapViewInSessionSpace is internally promoted to
  1067. // MmMapViewInSystemSpace on non-Hydra systems.
  1068. NtStatus = Win32MapViewInSessionSpace(fv.pSection, &fv.pvKView, &ViewSize);
  1069. #else
  1070. NtStatus = MmMapViewInSystemSpace(fv.pSection, &fv.pvKView, &ViewSize);
  1071. #endif
  1072. if (NT_SUCCESS(NtStatus))
  1073. {
  1074. #ifdef _HYDRA_
  1075. #if DBG
  1076. if (!G_fConsole)
  1077. {
  1078. DebugGreTrackAddMapView (fv.pvKView);
  1079. }
  1080. #endif
  1081. #endif
  1082. *pfvw = fv;
  1083. ReturnValue = TRUE;
  1084. }
  1085. else
  1086. {
  1087. DEREFERENCE_FONTVIEW_SECTION(fv.pSection);
  1088. }
  1089. }
  1090. return(ReturnValue);
  1091. }
  1092. /******************************Public*Routine******************************\
  1093. *
  1094. * vCopyDESIGNVECTOR
  1095. *
  1096. \**************************************************************************/
  1097. extern "C" VOID vCopyDESIGNVECTOR(DESIGNVECTOR *pDst, DESIGNVECTOR *pSrc)
  1098. {
  1099. RtlCopyMemory(pDst, pSrc, SIZEOFDV(pSrc->dvNumAxes));
  1100. }
  1101. /******************************Public*Routine******************************\
  1102. *
  1103. * EngMapFontFileFDInternal
  1104. *
  1105. \**************************************************************************/
  1106. BOOL EngMapFontFileFDInternal(
  1107. ULONG_PTR iFile ,
  1108. PULONG *ppjBuf,
  1109. ULONG *pcjBuf,
  1110. BOOL bFontDrv
  1111. )
  1112. {
  1113. PFONTFILEVIEW pffv = (PFONTFILEVIEW) iFile;
  1114. BOOL bMapIt,bRet;
  1115. FILEVIEW fv;
  1116. RtlZeroMemory(&fv, sizeof(fv));
  1117. bRet = TRUE;
  1118. bMapIt = TRUE;
  1119. GreAcquireFastMutex(ghfmMemory);
  1120. if (pffv->fv.pvViewFD)
  1121. {
  1122. bMapIt = FALSE;
  1123. pffv->cRefCountFD += 1;
  1124. }
  1125. else if (!pffv->pwszPath)
  1126. {
  1127. GreReleaseFastMutex(ghfmMemory);
  1128. return(FALSE);
  1129. }
  1130. else if (pffv->fv.pSection)
  1131. {
  1132. NTSTATUS NtStatus;
  1133. SIZE_T ViewSize;
  1134. LARGE_INTEGER SectionOffset;
  1135. SectionOffset.QuadPart = 0;
  1136. ViewSize = 0;
  1137. #if defined(_GDIPLUS_)
  1138. NtStatus = MapViewInProcessSpace(pffv->fv.pSection, &pffv->fv.pvViewFD, &ViewSize);
  1139. #else
  1140. NtStatus = MmMapViewOfSection(
  1141. pffv->fv.pSection , // SectionToMap,
  1142. gpepCSRSS , // spooler process
  1143. &pffv->fv.pvViewFD, // CapturedBase,
  1144. 0 , // ZeroBits,
  1145. ViewSize , // CommitSize,
  1146. &SectionOffset , // SectionOffset,
  1147. &ViewSize , // CapturedViewSize,
  1148. ViewUnmap , // InheritDisposition,
  1149. SEC_NO_CHANGE , // AllocationType,
  1150. PAGE_READONLY // Protect
  1151. );
  1152. #endif
  1153. if (bRet = NT_SUCCESS(NtStatus))
  1154. {
  1155. pffv->cRefCountFD = 1;
  1156. }
  1157. bMapIt = FALSE;
  1158. }
  1159. GreReleaseFastMutex(ghfmMemory);
  1160. if (bMapIt)
  1161. {
  1162. // If the call is from the font driver, the current thread
  1163. // is attached to the CSRSS process. By attaching it to the
  1164. // CSRSS, the thread loses its user security context which
  1165. // prevents the thread to open a network font file.
  1166. BOOL bCreateOK, bIsFAT;
  1167. if (bFontDrv)
  1168. KeDetachProcess();
  1169. bCreateOK = bCreateSection(pffv->pwszPath, &fv, 0, &bIsFAT);
  1170. if (bFontDrv)
  1171. KeAttachProcess(PsGetProcessPcb(gpepCSRSS));
  1172. if (!bCreateOK)
  1173. {
  1174. bRet = FALSE;
  1175. }
  1176. else
  1177. {
  1178. BOOL bKeepIt;
  1179. NTSTATUS NtStatus;
  1180. SIZE_T ViewSize = 0;
  1181. PVOID pvView, pSection;
  1182. LARGE_INTEGER SectionOffset = {0,0};
  1183. #if defined(_GDIPLUS_)
  1184. NtStatus = MapViewInProcessSpace(fv.pSection, &fv.pvViewFD, &ViewSize);
  1185. #else
  1186. NtStatus = MmMapViewOfSection(
  1187. fv.pSection , // SectionToMap,
  1188. gpepCSRSS , // spooler process
  1189. &fv.pvViewFD , // CapturedBase,
  1190. 0 , // ZeroBits,
  1191. ViewSize , // CommitSize,
  1192. &SectionOffset, // SectionOffset,
  1193. &ViewSize , // CapturedViewSize,
  1194. ViewUnmap , // InheritDisposition,
  1195. SEC_NO_CHANGE , // AllocationType,
  1196. PAGE_READONLY // Protect
  1197. );
  1198. #endif
  1199. if (!NT_SUCCESS(NtStatus))
  1200. {
  1201. DEREFERENCE_FONTVIEW_SECTION(fv.pSection);
  1202. return(FALSE);
  1203. }
  1204. GreAcquireFastMutex(ghfmMemory);
  1205. pffv->cRefCountFD += 1;
  1206. if (pffv->fv.pvViewFD)
  1207. {
  1208. bKeepIt = FALSE;
  1209. }
  1210. else
  1211. {
  1212. bRet = bKeepIt = bMapRoutine(pffv, &fv, ModeFD, bIsFAT);
  1213. }
  1214. GreReleaseFastMutex(ghfmMemory);
  1215. if (!bKeepIt)
  1216. {
  1217. vUnmapFileFD(&fv);
  1218. }
  1219. }
  1220. }
  1221. if (bRet)
  1222. {
  1223. ASSERTGDI((ULONG_PTR)pffv->fv.pvViewFD > 0x100000,
  1224. "csrss view smaller than 1MB \n");
  1225. if (ppjBuf)
  1226. {
  1227. *ppjBuf = (ULONG*) pffv->fv.pvViewFD;
  1228. }
  1229. if (pcjBuf)
  1230. {
  1231. *pcjBuf = pffv->fv.cjView;
  1232. }
  1233. }
  1234. return(bRet);
  1235. }
  1236. /************************Public*Routine**********************\
  1237. *
  1238. * EngMapFontFileFD
  1239. *
  1240. \************************************************************/
  1241. BOOL EngMapFontFileFD(
  1242. ULONG_PTR iFile,
  1243. PULONG *ppjBuf,
  1244. ULONG *pcjBuf
  1245. )
  1246. {
  1247. return (EngMapFontFileFDInternal(iFile, ppjBuf, pcjBuf, TRUE));
  1248. }
  1249. /******************************Public*Routine******************************\
  1250. *
  1251. * vUnmapFileFD
  1252. *
  1253. \**************************************************************************/
  1254. VOID vUnmapFileFD(FILEVIEW *pFileView)
  1255. {
  1256. #if defined(_GDIPLUS_)
  1257. UnmapViewInProcessSpace(pFileView->pvViewFD);
  1258. #else
  1259. MmUnmapViewOfSection(gpepCSRSS, pFileView->pvViewFD);
  1260. #endif
  1261. if (pFileView->pvKView == 0)
  1262. {
  1263. DEREFERENCE_FONTVIEW_SECTION(pFileView->pSection);
  1264. }
  1265. pFileView->bLastUpdated = FALSE;
  1266. }
  1267. /******************************Public*Routine******************************\
  1268. *
  1269. * EngUnmapFontFileFD
  1270. *
  1271. \**************************************************************************/
  1272. void EngUnmapFontFileFD(ULONG_PTR iFile)
  1273. {
  1274. FILEVIEW fv;
  1275. PFONTFILEVIEW pffv = (PFONTFILEVIEW) iFile;
  1276. fv.pvViewFD = NULL;
  1277. GreAcquireFastMutex(ghfmMemory);
  1278. if (pffv->cRefCountFD)
  1279. {
  1280. pffv->cRefCountFD -= 1;
  1281. if (pffv->cRefCountFD == 0)
  1282. {
  1283. if (pffv->pwszPath)
  1284. {
  1285. // This path is never taken for remote fonts
  1286. // so this routine does not unmap remote fonts
  1287. fv = pffv->fv; // copy pvKView, pvViewFD and pSection;
  1288. if (pffv->fv.pvViewFD)
  1289. {
  1290. pffv->fv.pvViewFD = 0;
  1291. if (pffv->fv.pvKView == 0)
  1292. {
  1293. pffv->fv.pSection = 0;
  1294. }
  1295. }
  1296. }
  1297. }
  1298. }
  1299. GreReleaseFastMutex(ghfmMemory);
  1300. if (fv.pvViewFD)
  1301. {
  1302. vUnmapFileFD(&fv);
  1303. }
  1304. }
  1305. /******************************Public*Routine******************************\
  1306. *
  1307. * bCreateSection
  1308. *
  1309. \**************************************************************************/
  1310. BOOL bCreateSection(PWSTR pwszFileName, FILEVIEW *pFileView, INT iFileSize, BOOL *pbIsFAT)
  1311. {
  1312. #if defined(_GDIPLUS_)
  1313. return CreateMemoryMappedSection(pwszFileName, pFileView, iFileSize);
  1314. #else // !_GDIPLUS_
  1315. UNICODE_STRING UnicodeString;
  1316. OBJECT_ATTRIBUTES ObjectAttributes;
  1317. NTSTATUS NtStatus;
  1318. HANDLE FileHandle = 0;
  1319. IO_STATUS_BLOCK IoStatusBlock;
  1320. FILE_STANDARD_INFORMATION FileStandardInfo;
  1321. FILE_BASIC_INFORMATION FileBasicInfo;
  1322. LARGE_INTEGER DesiredSize;
  1323. FILEVIEW FileView;
  1324. RtlZeroMemory(pFileView, sizeof(FILEVIEW));
  1325. RtlZeroMemory(&FileView, sizeof(FILEVIEW));
  1326. RtlInitUnicodeString(&UnicodeString, pwszFileName);
  1327. BOOLEAN oldErrorState = IoSetThreadHardErrorMode(FALSE);
  1328. InitializeObjectAttributes(
  1329. &ObjectAttributes,
  1330. &UnicodeString,
  1331. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1332. 0,
  1333. 0);
  1334. if (iFileSize)
  1335. {
  1336. NtStatus = IoCreateFile(
  1337. &FileHandle,
  1338. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  1339. &ObjectAttributes,
  1340. &IoStatusBlock,
  1341. 0,
  1342. FILE_ATTRIBUTE_NORMAL,
  1343. FILE_SHARE_READ
  1344. | FILE_SHARE_WRITE
  1345. | FILE_SHARE_DELETE,
  1346. FILE_OPEN_IF,
  1347. FILE_SYNCHRONOUS_IO_ALERT,
  1348. 0,
  1349. 0,
  1350. CreateFileTypeNone,
  1351. NULL,
  1352. IO_FORCE_ACCESS_CHECK | // Ensure the user has access to the file
  1353. IO_NO_PARAMETER_CHECKING | // All of the buffers are kernel buffers
  1354. IO_CHECK_CREATE_PARAMETERS);
  1355. }
  1356. else
  1357. {
  1358. // Here is the code for reference NtOpenFile
  1359. // File locates it at ..\ntos\io\open.c
  1360. //
  1361. NtStatus = IoCreateFile(
  1362. &FileHandle,
  1363. FILE_GENERIC_READ
  1364. | FILE_GENERIC_EXECUTE
  1365. | SYNCHRONIZE,
  1366. &ObjectAttributes,
  1367. &IoStatusBlock,
  1368. 0,
  1369. FILE_ATTRIBUTE_NORMAL,
  1370. FILE_SHARE_READ,
  1371. FILE_OPEN, // Flag for file open.
  1372. FILE_SYNCHRONOUS_IO_ALERT,
  1373. 0,
  1374. 0,
  1375. CreateFileTypeNone,
  1376. NULL,
  1377. IO_FORCE_ACCESS_CHECK | // Ensure the user has access to the file
  1378. IO_NO_PARAMETER_CHECKING | // All of the buffers are kernel buffers
  1379. IO_CHECK_CREATE_PARAMETERS);
  1380. }
  1381. IoSetThreadHardErrorMode(oldErrorState);
  1382. if (!NT_SUCCESS(NtStatus))
  1383. {
  1384. return(FALSE);
  1385. }
  1386. NtStatus = ZwQueryInformationFile(
  1387. FileHandle,
  1388. &IoStatusBlock,
  1389. &FileStandardInfo,
  1390. sizeof(FILE_STANDARD_INFORMATION),
  1391. FileStandardInformation);
  1392. if (!NT_SUCCESS(NtStatus))
  1393. {
  1394. ZwClose(FileHandle);
  1395. return(FALSE);
  1396. }
  1397. // Get the time stamp
  1398. NtStatus = ZwQueryInformationFile(
  1399. FileHandle,
  1400. &IoStatusBlock,
  1401. &FileBasicInfo,
  1402. sizeof(FileBasicInfo),
  1403. FileBasicInformation);
  1404. if (!NT_SUCCESS(NtStatus))
  1405. {
  1406. ZwClose(FileHandle);
  1407. return(FALSE);
  1408. }
  1409. FileView.LastWriteTime = FileBasicInfo.LastWriteTime;
  1410. FileView.bLastUpdated = TRUE;
  1411. if (pbIsFAT)
  1412. {
  1413. struct
  1414. {
  1415. FILE_FS_ATTRIBUTE_INFORMATION Info;
  1416. WCHAR Buffer[MAX_PATH];
  1417. } FileFsAttrInfoBuffer;
  1418. *pbIsFAT = FALSE;
  1419. NtStatus = ZwQueryVolumeInformationFile(
  1420. FileHandle,
  1421. &IoStatusBlock,
  1422. &FileFsAttrInfoBuffer.Info,
  1423. sizeof(FileFsAttrInfoBuffer),
  1424. FileFsAttributeInformation);
  1425. if (!NT_SUCCESS(NtStatus))
  1426. {
  1427. ZwClose(FileHandle);
  1428. return(FALSE);
  1429. }
  1430. if (!_wcsnicmp((LPWSTR)FileFsAttrInfoBuffer.Info.FileSystemName, L"FAT", 3))
  1431. {
  1432. *pbIsFAT = TRUE;
  1433. }
  1434. }
  1435. // Note that we must call ZwSetInformation even in the case where iFileSize
  1436. // is -1. By doing so we force the file time to change. It turns out that
  1437. // just mapping a file for write (and writing to the section) is not enough
  1438. // to cause the file time to change.
  1439. if (iFileSize)
  1440. {
  1441. if (iFileSize > 0)
  1442. {
  1443. DesiredSize.LowPart = (ULONG) iFileSize;
  1444. }
  1445. else
  1446. {
  1447. DesiredSize.LowPart = FileStandardInfo.EndOfFile.LowPart;
  1448. }
  1449. DesiredSize.HighPart = 0;
  1450. //
  1451. // set the file length to the requested size
  1452. //
  1453. NtStatus = ZwSetInformationFile(
  1454. FileHandle,
  1455. &IoStatusBlock,
  1456. &DesiredSize,
  1457. sizeof(DesiredSize),
  1458. FileEndOfFileInformation);
  1459. if (!NT_SUCCESS(NtStatus))
  1460. {
  1461. ZwClose(FileHandle);
  1462. return(FALSE);
  1463. }
  1464. //
  1465. // set FileStandardInfo and fall through to the case where we called
  1466. // ZwQueryInfo to get the file size
  1467. //
  1468. FileStandardInfo.EndOfFile.LowPart = (ULONG) DesiredSize.LowPart;
  1469. FileStandardInfo.EndOfFile.HighPart = 0;
  1470. }
  1471. if (FileStandardInfo.EndOfFile.HighPart)
  1472. {
  1473. ZwClose(FileHandle);
  1474. return(FALSE);
  1475. }
  1476. FileView.cjView = FileStandardInfo.EndOfFile.LowPart;
  1477. InitializeObjectAttributes(
  1478. &ObjectAttributes,
  1479. 0,
  1480. OBJ_KERNEL_HANDLE,
  1481. 0,
  1482. 0);
  1483. NtStatus = ZwWin32CreateSection(
  1484. &FileView.pSection,
  1485. SECTION_ALL_ACCESS,
  1486. &ObjectAttributes,
  1487. &FileStandardInfo.EndOfFile,
  1488. (iFileSize) ? PAGE_READWRITE : PAGE_EXECUTE_READ,
  1489. SEC_COMMIT,
  1490. FileHandle,
  1491. 0,
  1492. TAG_SECTION_CREATESECTION);
  1493. ZwClose(FileHandle);
  1494. if (!NT_SUCCESS(NtStatus))
  1495. {
  1496. return(FALSE);
  1497. }
  1498. RtlCopyMemory(pFileView, &FileView, sizeof(FileView));
  1499. return(TRUE);
  1500. #endif // !_GDIPLUS_
  1501. }
  1502. /******************************Public*Routine******************************\
  1503. * vUnmapFile
  1504. *
  1505. * Unmaps file whose view is based at pv
  1506. *
  1507. * Called by:
  1508. *
  1509. * EngMapFontFile
  1510. * EngUnmapFontFile
  1511. * GetTypeOneFontList
  1512. *
  1513. * 14-Dec-1990 -by- Bodin Dresevic [BodinD]
  1514. * Wrote it.
  1515. \**************************************************************************/
  1516. VOID vUnmapFile(PFILEVIEW pfv)
  1517. {
  1518. NTSTATUS NtStatus;
  1519. #if defined(_GDIPLUS_)
  1520. NtStatus = UnmapViewInProcessSpace(pfv->pvKView);
  1521. #elif defined(_HYDRA_)
  1522. // MmUnmapViewInSessionSpace is internally promoted to
  1523. // MmUnmapViewInSystemSpace on non-Hydra systems.
  1524. NtStatus = Win32UnmapViewInSessionSpace(pfv->pvKView);
  1525. #else
  1526. MmUnmapViewInSystemSpace(pfv->pvKView);
  1527. #endif
  1528. #if DBG && defined(_HYDRA_)
  1529. if ((!G_fConsole) && (NT_SUCCESS(NtStatus)))
  1530. {
  1531. DebugGreTrackRemoveMapView(pfv->pvKView);
  1532. }
  1533. #endif
  1534. if (pfv->pvViewFD == 0)
  1535. {
  1536. DEREFERENCE_FONTVIEW_SECTION(pfv->pSection);
  1537. }
  1538. pfv->bLastUpdated = FALSE;
  1539. }
  1540. /******************************Public*Routine******************************\
  1541. * GetModuleHandleAndIncrementRefcount
  1542. *
  1543. * This function searches through the GreEngLoadModuleAllocList to see
  1544. * if a module has been loaded already, and if so it returns a handle
  1545. * to that module (and increments the reference count).
  1546. *
  1547. * Arguments:
  1548. *
  1549. * pwsz -- The name of the module
  1550. *
  1551. * Return Value:
  1552. *
  1553. * a FILEVIEW pointer if the module has been loaded already, NULL
  1554. * otherwise.
  1555. *
  1556. * History:
  1557. *
  1558. * 21-Apr-1998 -by- Ori Gershony [orig]
  1559. *
  1560. \**************************************************************************/
  1561. HANDLE
  1562. GetModuleHandleAndIncrementRefcount(
  1563. PWSZ pwsz
  1564. )
  1565. {
  1566. HANDLE hRet=NULL;
  1567. if (GreEngLoadModuleAllocListLock) GreAcquireSemaphore(GreEngLoadModuleAllocListLock);
  1568. PLIST_ENTRY pNextEntry = GreEngLoadModuleAllocList.Flink;
  1569. //
  1570. // Loop through the loaded modules looking for pwsz
  1571. //
  1572. while ((pNextEntry != &GreEngLoadModuleAllocList) && !(hRet))
  1573. {
  1574. PWSZ pwszModuleName = (PWSZ) (((PBYTE) pNextEntry) + sizeof(ENGLOADMODULEHDR) -
  1575. ((PENGLOADMODULEHDR)pNextEntry)->cjSize);
  1576. if (_wcsicmp(pwsz, pwszModuleName) == 0)
  1577. {
  1578. ((PENGLOADMODULEHDR)pNextEntry)->cRef++;
  1579. hRet = (HANDLE) (((PBYTE) pNextEntry) + sizeof(ENGLOADMODULEHDR));
  1580. }
  1581. pNextEntry = pNextEntry->Flink;
  1582. }
  1583. if (GreEngLoadModuleAllocListLock) GreReleaseSemaphore(GreEngLoadModuleAllocListLock);
  1584. return hRet;
  1585. }
  1586. /******************************Public*Routine******************************\
  1587. *
  1588. * LoadModuleWorkHorse
  1589. *
  1590. * Note that all allocations are tracked through a linked list maintained
  1591. * via the ENGLOADMODULEHDR fields. This enables us to do just one allocation
  1592. * per file even if called multiple times. The diagram below shows the layout
  1593. * of the data structures in memory.
  1594. *
  1595. *
  1596. *
  1597. * Buffer
  1598. * pBaseAlloc --> +------------------+<-|
  1599. * | Module name | |
  1600. * pelmNew --> +------------------+ |-cjSize (length of module name
  1601. * | ENGLOADMODULEHDR | | plus ENGLOADMODULE header)
  1602. * pfv --> +------------------+<-|
  1603. * | FILEVIEW |
  1604. * | |
  1605. * +------------------+
  1606. *
  1607. *
  1608. * Note that it is theoretically possible for two modules with the same name
  1609. * to be mapped twice (to two different virtual addresses), because we don't
  1610. * grab the GreEngLoadModuleAllocListLock until late in the code (so if two
  1611. * threads enter this function and both pass the search stage before either
  1612. * grabs the lock, both would independently get different entries for this
  1613. * module). There are two possible ways to remedy this:
  1614. * 1) Grab the lock before the search -- the problem is that this will force
  1615. * us to keep the lock during the call to bMapFile which can take a while
  1616. * 2) Search twice, the second time being after the call to bMapFile (and after
  1617. * we obtain the lock). This is quite ugly, and would force us to free the
  1618. * memory allocated by bMapFile in the scenario described above.
  1619. *
  1620. * So because neither solution is particularly attractive, we allow the same
  1621. * module to be placed multiple times in the list. In practice this should
  1622. * happen very rarely, and shouldn't lead to any major problems (except
  1623. * for a minor waste of resources).
  1624. *
  1625. *
  1626. \**************************************************************************/
  1627. HANDLE LoadModuleWorkHorse(PWSZ pwsz, INT iSize)
  1628. {
  1629. UNICODE_STRING usPath;
  1630. BYTE *pBaseAlloc;
  1631. FILEVIEW *pfv;
  1632. HANDLE hRet = 0;
  1633. ULONGSIZE_T cj = sizeof(FILEVIEW);
  1634. ULONG cjStringLength;
  1635. //
  1636. // NULL names are bad.
  1637. //
  1638. if (wcslen(pwsz) == 0)
  1639. {
  1640. return NULL;
  1641. }
  1642. //
  1643. // First check if this is mapped into kernel memory already
  1644. //
  1645. if (iSize == 0) // Only share on EngLoadModule calls because iSize may not be the same
  1646. {
  1647. if ((hRet = GetModuleHandleAndIncrementRefcount(pwsz)) != NULL)
  1648. {
  1649. return hRet;
  1650. }
  1651. }
  1652. //
  1653. // Get the name of the module length string. Round up to a multiple of
  1654. // 8 bytes so that the buffer we return will be 8-byte aligned (ENGLOADMODULEHDR is
  1655. // already 8-byte aligned).
  1656. //
  1657. cjStringLength = (wcslen(pwsz) + 1) * sizeof(WCHAR);
  1658. cjStringLength = ((cjStringLength + 7) & (~7));
  1659. //
  1660. // Increase the size of the allocation by the size of the ENGLOADMODULEHDR header
  1661. // plus the length of the string.
  1662. //
  1663. cj += sizeof(ENGLOADMODULEHDR) + cjStringLength;
  1664. if (MakeSystemRelativePath(pwsz, &usPath, FALSE))
  1665. {
  1666. if (pBaseAlloc = (BYTE *) PALLOCMEM(cj, 'lifG'))
  1667. {
  1668. ENGLOADMODULEHDR *pelmNew = (ENGLOADMODULEHDR *) (pBaseAlloc + cjStringLength);
  1669. pfv = (FILEVIEW *) (pelmNew + 1);
  1670. if (bMapFile(usPath.Buffer, pfv, iSize, NULL))
  1671. {
  1672. hRet = pfv;
  1673. //
  1674. // Copy the filename into the buffer
  1675. //
  1676. if (iSize==0)
  1677. {
  1678. //
  1679. // EngLoadModule -- share with other calls
  1680. //
  1681. wcscpy((PWSZ)pBaseAlloc, pwsz);
  1682. }
  1683. else
  1684. {
  1685. //
  1686. // EngLoadModuleForWrite -- don't share because of possible buffer size mismatches
  1687. // It is possible to code this so that writeable modules would be shared
  1688. // as well (store size in the ENGLOADMODULEHDR), but I don't think this case
  1689. // will happen very frequently so the benefit of doing this is very small.
  1690. //
  1691. wcscpy((PWSZ)pBaseAlloc, L"");
  1692. }
  1693. //
  1694. // Setup the ENGLOADMODULEHDR
  1695. //
  1696. pelmNew->cRef = 1;
  1697. pelmNew->cjSize = sizeof(ENGLOADMODULEHDR) + cjStringLength;
  1698. //
  1699. // Now add to the tracking list
  1700. //
  1701. if (GreEngLoadModuleAllocListLock) GreAcquireSemaphore(GreEngLoadModuleAllocListLock);
  1702. InsertTailList(&GreEngLoadModuleAllocList, &(pelmNew->list));
  1703. if (GreEngLoadModuleAllocListLock) GreReleaseSemaphore(GreEngLoadModuleAllocListLock);
  1704. }
  1705. else
  1706. {
  1707. VFREEMEM(pBaseAlloc);
  1708. }
  1709. }
  1710. VFREEMEM(usPath.Buffer);
  1711. }
  1712. return(hRet);
  1713. }
  1714. /*******************************************************************************
  1715. * EngLoadModuleForWrite
  1716. *
  1717. * History:
  1718. * 4/24/1995 by Gerrit van Wingerden [gerritv]
  1719. * Wrote it.
  1720. *******************************************************************************/
  1721. HANDLE EngLoadModuleForWrite(PWSZ pwsz, ULONG cjSizeOfModule)
  1722. {
  1723. return(LoadModuleWorkHorse(pwsz, cjSizeOfModule ? cjSizeOfModule : -1));
  1724. }
  1725. /*******************************************************************************
  1726. * EngLoadModule
  1727. *
  1728. * History:
  1729. * 4/24/1995 by Gerrit van Wingerden [gerritv]
  1730. * Wrote it.
  1731. *******************************************************************************/
  1732. HANDLE EngLoadModule(PWSZ pwsz)
  1733. {
  1734. return(LoadModuleWorkHorse(pwsz, 0));
  1735. }
  1736. /****************************************************************************
  1737. * EngFreeModule()
  1738. *
  1739. * History:
  1740. * 4/27/1995 by Gerrit van Wingerden [gerritv]
  1741. * Wrote it.
  1742. *****************************************************************************/
  1743. VOID EngFreeModule(HANDLE h)
  1744. {
  1745. ULONG cRef;
  1746. if (h)
  1747. {
  1748. ENGLOADMODULEHDR *pelmVictim = (ENGLOADMODULEHDR *) h;
  1749. pelmVictim--; // Now it points to the real ENGLOADMODULEHDR
  1750. //
  1751. // Enforce synchronization on the linked list
  1752. //
  1753. if (GreEngLoadModuleAllocListLock) GreAcquireSemaphore(GreEngLoadModuleAllocListLock);
  1754. pelmVictim->cRef--; // Decrement reference count
  1755. //
  1756. // Remove resource if necessary. Cache cRef in a local variable in case it gets
  1757. // modified by another thread after we exit the critical section.
  1758. //
  1759. if ((cRef=pelmVictim->cRef) == 0)
  1760. {
  1761. RemoveEntryList(&(pelmVictim->list));
  1762. }
  1763. //
  1764. // Restore IRQL level as soon as possible
  1765. //
  1766. if (GreEngLoadModuleAllocListLock) GreReleaseSemaphore(GreEngLoadModuleAllocListLock);
  1767. //
  1768. // If removing resource still need to unmap file and free headers memory
  1769. //
  1770. if (cRef == 0)
  1771. {
  1772. //
  1773. // Dereference section and unmap the file
  1774. //
  1775. vUnmapFile((FILEVIEW *)h);
  1776. //
  1777. // Free allocated memory
  1778. //
  1779. VFREEMEM (((PBYTE) h) - pelmVictim->cjSize);
  1780. }
  1781. }
  1782. }
  1783. /****************************************************************************
  1784. * PVOID EngMapModule( HANDLE, PULONG )
  1785. *
  1786. * History:
  1787. * 5/25/1995 by Gerrit van Wingerden [gerritv]
  1788. * Wrote it.
  1789. *****************************************************************************/
  1790. PVOID EngMapModule(HANDLE h, PULONG pSize)
  1791. {
  1792. *pSize=((PFILEVIEW)h)->cjView;
  1793. return(((PFILEVIEW)h)->pvKView);
  1794. }
  1795. /******************************Public*Routine******************************\
  1796. * BOOL EngMapFile
  1797. *
  1798. * Create or Open a file and map it into system space. The file is extended or
  1799. * truncated according to the cjSize passed in. If cjSize == 0, the file size
  1800. * is unchanged. The view is always mapped on the entire file.
  1801. *
  1802. * Parameters
  1803. * IN pwsz - Name of the file to be mapped.
  1804. * Filename has to be fully qualified. ex. L"\\??\\c:\\test.dat"
  1805. * IN cjSize - Size of the file.
  1806. * OUT iFile - identifier of the mapped file
  1807. *
  1808. * Return Value
  1809. * Pointer to the memory view.
  1810. *
  1811. * History:
  1812. * 4-Nov-1996 -by- Lingyun Wang [LingyunW]
  1813. * 19-Nov-1998 -by- Lingyun Wang [lingyunw] changed interface
  1814. *
  1815. * Wrote it.
  1816. \**************************************************************************/
  1817. PVOID EngMapFile(PWSZ pwsz, ULONG cjSize, ULONG_PTR *piFile)
  1818. {
  1819. FILEVIEW *pfv;
  1820. PVOID ReturnValue = 0;
  1821. if (pfv = (FILEVIEW*) PALLOCMEM(sizeof(FILEVIEW), 'lifG'))
  1822. {
  1823. if (bMapFile(pwsz, pfv, cjSize ? cjSize : -1, NULL))
  1824. {
  1825. *piFile = (ULONG_PTR)pfv;
  1826. ReturnValue = pfv->pvKView;
  1827. }
  1828. else
  1829. {
  1830. *piFile = 0;
  1831. VFREEMEM(pfv);
  1832. }
  1833. }
  1834. return(ReturnValue);
  1835. }
  1836. /******************************Public*Routine******************************\
  1837. * BOOL EngUnmapFile
  1838. *
  1839. * Unmap a view of file in system space
  1840. **
  1841. * Return Value
  1842. * TRUE
  1843. * FALSE
  1844. *
  1845. * History:
  1846. * 4-Nov-1996 -by- Lingyun Wang [LingyunW]
  1847. * Wrote it.
  1848. \**************************************************************************/
  1849. BOOL EngUnmapFile(ULONG_PTR iFile)
  1850. {
  1851. NTSTATUS NtStatus;
  1852. FILEVIEW *pfv = (FILEVIEW *)iFile;
  1853. if (iFile)
  1854. {
  1855. #if defined(_GDIPLUS_)
  1856. NtStatus = UnmapViewInProcessSpace(pfv->pvKView);
  1857. #elif defined(_HYDRA_)
  1858. // MmUnmapViewInSessionSpace is internally promoted to
  1859. // MmUnmapViewInSystemSpace on non-Hydra systems.
  1860. NtStatus = Win32UnmapViewInSessionSpace(pfv->pvKView);
  1861. #else
  1862. MmUnmapViewInSystemSpace(pfv->pvKView);
  1863. #endif
  1864. #if DBG && defined(_HYDRA_)
  1865. if ((!G_fConsole) && (NT_SUCCESS(NtStatus)))
  1866. {
  1867. DebugGreTrackRemoveMapView(pfv->pvKView);
  1868. }
  1869. #endif
  1870. DEREFERENCE_FONTVIEW_SECTION(pfv->pSection);
  1871. VFREEMEM(pfv);
  1872. return(NT_SUCCESS(NtStatus));
  1873. }
  1874. else
  1875. {
  1876. return (FALSE);
  1877. }
  1878. }
  1879. /******************************Public*Routine******************************\
  1880. * BOOL bIsOneHourDifference()
  1881. *
  1882. *
  1883. * History:
  1884. * 15-April-1999 -by- Xudong Wu [TessieW]
  1885. * Wrote it.
  1886. \**************************************************************************/
  1887. // one tick is 100ns, us = 10 tick, s = 10*1000*1000 tick
  1888. // 1hr = 10*1000*1000*60*60
  1889. #define ONEHOUR (10i64*1000i64*1000i64*60i64*60i64)
  1890. BOOL bIsOneHourDifference(FILEVIEW *pNew, FILEVIEW *pOld)
  1891. {
  1892. LONGLONG llDifference = pNew->LastWriteTime.QuadPart - pOld->LastWriteTime.QuadPart;
  1893. if(llDifference < 0) llDifference = -llDifference;
  1894. return (llDifference == ONEHOUR ? TRUE : FALSE);
  1895. }
  1896. /******************************Public*Routine******************************\
  1897. *
  1898. * bShouldMap // the font file
  1899. *
  1900. \**************************************************************************/
  1901. BOOL bShouldMap(FILEVIEW *pNew, FILEVIEW *pOld, BOOL bIsFAT)
  1902. {
  1903. BOOL bMapRet = FALSE;
  1904. if (pOld->LastWriteTime.QuadPart != 0) // file had been mapped in the past
  1905. {
  1906. if (pOld->cjView == pNew->cjView)
  1907. {
  1908. // we consider the new and the old times the "same" if they
  1909. // are literally the same or if on the FAT system they differ by
  1910. // 1 hour which we think is likely the result of the daylight
  1911. // time saving change:
  1912. if
  1913. (
  1914. (pOld->LastWriteTime.QuadPart == pNew->LastWriteTime.QuadPart) ||
  1915. (bIsFAT && bIsOneHourDifference(pNew, pOld))
  1916. || gbGUISetup
  1917. )
  1918. {
  1919. bMapRet = TRUE;
  1920. }
  1921. }
  1922. }
  1923. else // first time we are attempting to map this file
  1924. {
  1925. bMapRet = TRUE;
  1926. }
  1927. return(bMapRet);
  1928. }
  1929. /******************************Public*Routine******************************\
  1930. *
  1931. * bMapRoutine
  1932. *
  1933. \**************************************************************************/
  1934. BOOL bMapRoutine(FONTFILEVIEW *pffv, FILEVIEW *pfv, MAP_MODE Mode, BOOL bIsFAT)
  1935. {
  1936. BOOL bKeepIt = bShouldMap(pfv, &pffv->fv, bIsFAT);
  1937. if (bKeepIt)
  1938. {
  1939. //
  1940. // This is the first time that this file has been mapped
  1941. // OR the file has not really changed since it was mapped
  1942. // last time, however, because the time zone changed and
  1943. // because of the bug in the
  1944. // FAT file system, LastWriteTime is now reported different.
  1945. if (Mode == ModeFD)
  1946. {
  1947. pffv->fv.pvViewFD = pfv->pvViewFD;
  1948. }
  1949. else
  1950. {
  1951. pffv->fv.pvKView = pfv->pvKView;
  1952. }
  1953. pffv->fv.cjView = pfv->cjView;
  1954. pffv->fv.LastWriteTime = pfv->LastWriteTime;
  1955. pffv->fv.pSection = pfv->pSection;
  1956. pffv->fv.bLastUpdated = TRUE;
  1957. }
  1958. else
  1959. {
  1960. // if the size or the time of the last write has changed
  1961. // then someone has switched the file or tampered with it
  1962. // while we had it unlocked. We will fail the call.
  1963. if (Mode == ModeFD)
  1964. {
  1965. pffv->cRefCountFD -= 1;
  1966. pffv->fv.pvViewFD = 0;
  1967. }
  1968. else
  1969. {
  1970. pffv->cKRefCount -= 1; // Restore FONTFILEVIEW
  1971. pffv->fv.pvKView = 0; // to original state
  1972. }
  1973. pffv->fv.bLastUpdated = FALSE;
  1974. }
  1975. return(bKeepIt);
  1976. }